我是Go的新手,我想了解为什么下面的代码段无法编译。将函数作为可能具有任何返回类型的函数参数接受的Go方式是什么?
package main
func main() {
test(a) // Error: cannot use a (type func() string) as type func() interface {} in argument to test
test(b) // Error: cannot use b (type func() int) as type func() interface {} in argument to test
}
func a() string {
return "hello"
}
func b() int {
return 1
}
func test(x func() interface{}) {
// some code...
v := x()
// some more code....
}
播放:https://play.golang.org/p/CqbuEZGy12
我的解决方案基于Volker的回答:
package main
import (
"fmt"
)
func main() {
// Wrap function a and b with an anonymous function
// that has an empty interface return type. With this
// anonymous function, the call signature of test
// can be satisfied without needing to modify the return
// type of function a and b.
test(func() interface{} {
return a()
})
test(func() interface{} {
return b()
})
}
func a() string {
return "hello"
}
func b() int {
return 1
}
func test(x func() interface{}) {
v := x()
fmt.Println(v)
}
答案 0 :(得分:11)
你为Go新手绊倒了一个非常常见的误解:空接口interface{}
不意味着“任何类型”。真的,它没有。 Go是静态类型的。空接口interface {}
是实际的(强类型类型),例如string
或struct{Foo int}
或interface{Explode() bool}
。
这意味着如果某个类型interface{}
具有该类型而不是“任何类型”。
你的功能
func test(x func() interface{})
需要一个参数。此参数是(无参数函数),它返回特定类型,类型interface{}
。您可以将任何函数传递给符合此签名的test
:“无参数并返回interface{}
”。您的所有功能a
和b
都不符合此签名。
如上所述:interface {}
不是“what”的神奇缩写,它是一种独特的静态类型。
你必须改变,例如a至:
func a() interface{} {
return "hello"
}
现在,当您返回不属于string
类型的interface{}
时,这可能会显得很奇怪。这是有效的,因为任何类型都可以赋值给interface{}
类型的变量(因为每种类型都至少没有方法:-)。
答案 1 :(得分:2)
正如Go specification所述:
函数类型表示具有相同参数的所有函数的集合,结果类型
在您的情况下,结果类型不同(string
vs interface{}
)
为了能够接收任何类型的结果类型的函数,test
必须定义为:
func text(x interface{}) { ... }
然后您必须使用reflect package来调用x
中存储的函数。
修改强>
这样的test
函数看起来像这样:
func test(x interface{}) {
v := reflect.ValueOf(x)
if v.Kind() != reflect.Func {
panic("Test requires a function")
}
t := v.Type()
if t.NumIn() != 0 && t.NumOut() != 1 {
panic("Function type must have no input parameters and a single return value")
}
values := v.Call(nil)
val := values[0].Interface()
// some more code..
}