英文:
Use of go's struct pointer as interface
问题
我想将结构体方法作为函数值传递。为什么如果函数要求返回interface{},而它返回struct,编译会失败?如果我尝试从声明为返回interface{}的函数(包装函数)返回struct,它完全可以工作。
package main
func main() {
println("hello")
testInterface(wrapper) // 可以工作
instance := MyStruct{}
testInterface(instance.works) // 可以工作
testInterface(instance.fails) // 失败:./main.go:8: cannot use instance.fails (type func(int) *MyStruct) as type func(int) interface {} in argument to testInterface
}
func testInterface(f func() interface{}) {
f()
return
}
type MyStruct struct {
}
func (s *MyStruct) works() interface{} {
return s
}
func (s *MyStruct) fails() *MyStruct {
return s
}
func wrapper() interface{} {
s := MyStruct{}
return s.fails()
}
编译失败是因为testInterface函数要求传入的函数类型是func() interface{},而instance.fails的类型是func(int) *MyStruct,二者不匹配。你可以尝试将instance.fails的返回类型更改为interface{},这样就可以通过编译了。
英文:
I want to pass struct method as function value. Why does compilation fail if function is required to return interface{} and it returns *struct? It perfectly works if I try to return *struct from function that is declared to return interface{} (wrapper func).
package main
func main() {
println("hello")
testInterface(wrapper) // works
instance := MyStruct{}
testInterface(instance.works) // works
testInterface(instance.fails) // fails: ./main.go:8: cannot use instance.fails (type func(int) *MyStruct) as type func(int) interface {} in argument to testInterface
}
func testInterface(f func() interface{}) {
f()
return
}
type MyStruct struct {
}
func (s *MyStruct) works() interface{} {
return s
}
func (s *MyStruct) fails() *MyStruct {
return s
}
func wrapper() interface{} {
s := MyStruct{}
return s.fails()
}
答案1
得分: 4
这是要翻译的内容:
这是因为它不符合可赋值性的条件。
- 如果满足以下任一情况,值
x可以赋值给类型T的变量("x可以赋值给T"):x的类型与T完全相同。x的类型V和T具有相同的基础类型,并且V或T中至少有一个不是命名类型。T是一个接口类型,并且x实现了T。x是一个双向通道值,T是一个通道类型,x的类型V和T具有相同的元素类型,并且V或T中至少有一个不是命名类型。x是预声明的标识符nil,而T是指针、函数、切片、映射、通道或接口类型。x是一个可以用类型T表示的无类型常量。
因此,这解释了为什么testInterface(instance.fails)失败:因为instance.fails不能赋值给f func() interface{}。
现在是第二个问题:
如果我尝试从声明为返回interface{}的函数(包装函数)返回*struct,它完全可以工作。
这可以正常工作,因为*struct类型的值可以赋值给interface{}类型,原因如下:
- 可赋值性规则中的这条规则:“
T是一个接口类型,并且x实现了T。” - “一个类型可以实现包含其方法子集的任何接口,因此可以实现多个不同的接口。例如,所有类型都实现空接口:”(粗体为我添加)
参考资料:
英文:
That's because it does not fit the assignability criterias
> A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:
>
> * x's type is identical to T.
> * x's type V and T have identical underlying types and at least one of V or T is not a named type.
> * T is an interface type and x implements T.
> * x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.
> * x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
> * x is an untyped constant representable by a value of type T.
So, this explains why testInterface(instance.fails) fails: because the instance.fails is not assignable to the f func() interface{}.
Now the second question:
> It perfectly works if I try to return *struct from function that is declared to return interface{} (wrapper func).
It works fine, because the value of the *struct type is assignable to the interface{} type because of:
- this rule of the assignability: "
Tis an interface type andximplementsT." - "A type implements any interface comprising any subset of its methods and may therefore implement several distinct interfaces. For instance, all types implement the empty interface:" (bold is mine)
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论