使用泛型:type *T 是指向类型参数的指针,而不是类型参数
Go with Generics: type *T is pointer to type parameter, not type parameter
大概是golang初学者的问题:)
我在尝试编译以下代码时遇到以下编译器错误。
我想为共享公共 ID 字段的不同类型(这里是 A 和 B)实现一个对象存储。按照 DRY 的想法,我想使用泛型来实现商店。
添加对象时,我想通过GS接口设置它的ID字段(当然实际代码会复杂一点),但是编译器不希望我这样做
./prog.go:29:7: item.SetId undefined (type *T is pointer to type parameter, not type parameter)
./prog.go:34:24: A does not implement GS (SetId method has pointer receiver)
有推荐的解决方法吗?提前致谢!!
package main
import "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())
}
关于使用*T
简而言之,类型参数不是它的约束。该约束仅确定在 T
上可用的操作,并不意味着有关 *T
的任何内容,它现在只是一个未命名的指针类型。是这个意思:
type *T is pointer to type parameter, not type parameter
因此,在您的情况下,*T
的方法集不会自动包含在 T
的具体类型 A
上声明的指针接收器方法,并且它不实现将由 *A
.
实现的接口
您必须通过设置额外的约束将其明确告知编译器。在简化形式中,它将类似于:
func Foo[T any, PT interface { SetId(string); *T}](v T) {}
您可以在此处找到有关此用例的更多示例和变体:
关于实施约束
此实例化 &MyStore[A]{}
失败的原因已由错误消息清楚地报告:
A does not implement GS (SetId method has pointer receiver)
换句话说,SetId()
是在 *A
上声明的,而不是 A
。因此,您应该使用 *A
:
实例化 MyStore
var storeA = &MyStore[*A]{}
然后将 struct/method 定义中出现的 *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{})
.
大概是golang初学者的问题:)
我在尝试编译以下代码时遇到以下编译器错误。
我想为共享公共 ID 字段的不同类型(这里是 A 和 B)实现一个对象存储。按照 DRY 的想法,我想使用泛型来实现商店。
添加对象时,我想通过GS接口设置它的ID字段(当然实际代码会复杂一点),但是编译器不希望我这样做
./prog.go:29:7: item.SetId undefined (type *T is pointer to type parameter, not type parameter)
./prog.go:34:24: A does not implement GS (SetId method has pointer receiver)
有推荐的解决方法吗?提前致谢!!
package main
import "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())
}
关于使用*T
简而言之,类型参数不是它的约束。该约束仅确定在 T
上可用的操作,并不意味着有关 *T
的任何内容,它现在只是一个未命名的指针类型。是这个意思:
type *T is pointer to type parameter, not type parameter
因此,在您的情况下,*T
的方法集不会自动包含在 T
的具体类型 A
上声明的指针接收器方法,并且它不实现将由 *A
.
您必须通过设置额外的约束将其明确告知编译器。在简化形式中,它将类似于:
func Foo[T any, PT interface { SetId(string); *T}](v T) {}
您可以在此处找到有关此用例的更多示例和变体:
关于实施约束
此实例化 &MyStore[A]{}
失败的原因已由错误消息清楚地报告:
A does not implement GS (SetId method has pointer receiver)
换句话说,SetId()
是在 *A
上声明的,而不是 A
。因此,您应该使用 *A
:
MyStore
var storeA = &MyStore[*A]{}
然后将 struct/method 定义中出现的 *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{})
.