Go语言中指针接收器在深度泛型结构中是否会预期失败?
泛型结构体方法调用指针接收器失败的原因及解决办法
正常运行的代码(普通函数调用指针接收器)
package main import "fmt" type C struct { GUID string } func (c *C) guid() string { return c.GUID } type I interface { C } type P interface { cc() } func constructor[T I]() T { return T{} } func main() { b := constructor[C]() x := &b fmt.Println("<" + x.guid() + ">") }
运行失败的代码(泛型结构体方法调用指针接收器)
package main import "fmt" type C struct { GUID string } func (c *C) guid() string { return c.GUID } type I interface { C } type E[T I] struct { Body T } func constructor[T I]() E[T] { return E[T]{} } func (e E[T]) guid() string { x := &e.Body return x.guid() } func main() { e := constructor[C]() fmt.Printf("%+v", e) fmt.Println(e.guid()) }
报错原因
这段代码报错的核心问题在于:接口I仅约束了类型参数T是C类型,但编译器无法推断*T(也就是*C)的方法集——虽然我们知道*C实现了guid,但对于泛型中的类型参数T,编译器只认接口约束里明确规定的内容。
而第一个正常运行的代码中,b是具体的C类型,&b是明确的*C,编译器清楚它有guid方法,所以能正常调用。
修复方案
方案1:修改接口约束,直接要求实现目标方法
把接口I改成约束类型必须实现guid方法,这样不管是值类型还是指针类型,只要符合方法要求就能用:
package main import "fmt" type C struct { GUID string } func (c *C) guid() string { return c.GUID } // 修改接口,约束必须实现guid方法 type I interface { guid() string } type E[T I] struct { Body T } func constructor[T I](val T) E[T] { return E[T]{Body: val} } func (e E[T]) guid() string { // Go会自动处理值类型调用指针接收器的情况 return e.Body.guid() } func main() { e := constructor(&C{}) fmt.Printf("%+v", e) fmt.Println(e.guid()) }
方案2:约束指针类型作为类型参数
如果只打算用指针类型作为泛型参数,可以直接约束T为*C的接口:
package main import "fmt" type C struct { GUID string } func (c *C) guid() string { return c.GUID } // 约束T是*C类型 type I interface { ~*C } type E[T I] struct { Body T } func constructor[T I]() E[T] { return E[T]{Body: new(C)} } func (e E[T]) guid() string { return e.Body.guid() } func main() { e := constructor[*C]() fmt.Printf("%+v", e) fmt.Println(e.guid()) }
内容的提问来源于stack exchange,提问作者Eldhenn
相关产品推荐
相关产品推荐

