英文:
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: "
T
is an interface type andx
implementsT
." - "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:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论