可能是 golang 初學者的問題:)嘗試編譯下面的代碼時,我遇到了以下編譯器錯誤。我想為共享公共 ID 字段的不同類型(這里是 A 和 B)實現一個對象存儲。按照 DRY 的想法,我想使用泛型來實現商店。添加一個對象時,我想使用GS接口設置它的ID字段(當然實際代碼要復雜一些),但是編譯器不希望我這樣做。./prog.go:29:7: item.SetId 未定義(type *T 是指向類型參數的指針,而不是類型參數)./prog.go:34:24: A沒有實現GS(SetId方法有指針接收者)有推薦的方法來解決這個問題嗎?提前致謝?。ackage mainimport "fmt"type A struct { ID string AMember string}type B struct { ID string BMember string}type GS interface { Id() string SetId(string)}func (s A) Id() string { return s.ID }func (s *A) SetId(i string) { s.ID = i }func (s B) Id() string { return s.ID }func (s *B) SetId(i string) { s.ID = i }type MyStore[T GS] struct { values map[string]*T}func (s *MyStore[T]) add(item *T) { item.SetId("aa") s.values["aa"] = item}func main() { var storeA = &MyStore[A]{} storeA.values = make(map[string]*A) a := &A{} storeA.add(a) fmt.Println(a.Id())}
1 回答

侃侃爾雅
TA貢獻1801條經驗 獲得超16個贊
關于使用 *T
簡而言之,類型參數不是它的約束。該約束僅確定 上可用的操作T
,它并不暗示關于 的任何內容*T
,它現在只是一個未命名的指針類型。這是意義:
type *T 是指向類型參數的指針,而不是類型參數
因此,與您的情況一樣,方法集*T
不會自動包含在T
具體類型上聲明的指針接收器方法A
,并且它不會實現將由 實現的接口*A
。
您必須通過設置額外的約束將其明確告知編譯器。在簡化形式中,它類似于:
func Foo[T any, PT interface { SetId(string); *T}](v T) {}
您可以在此處找到有關此用例的更多示例和變體:
關于實施約束
&MyStore[A]{}
錯誤消息清楚地報告了此實例化失敗的原因:
A沒有實現GS(SetId方法有指針接收者)
換句話說SetId()
,聲明于*A
,而不是A
。因此你應該實例MyStore
化*A
:
var storeA = &MyStore[*A]{}
然后*T
將結構/方法定義中的出現更改為T
:
type MyStore[T GS] struct { values map[string]T // just T instead of *T } func (s *MyStore[T]) add(item T) { }
在使用字段類型實例化時,*A
將變得等效于map[string]*A
因此使分配storeA.values = make(map[string]*A)
有效,并且方法簽名add(item *A)
因此允許storeA.add(&A{})
.
固定游樂場:https ://gotipplay.golang.org/p/dcUVJ5YQK_b
- 1 回答
- 0 關注
- 123 瀏覽
添加回答
舉報
0/150
提交
取消