任何类型的对象都可以分配给空接口(interface)。比如我们有如下函数
func Println(i interface{} ) {
fmt.Println(i)
}
我们可以这样调用它
Println(3)
Println(1.5)
Println("Hello")
但是对于函数类型我不能实现同样的事情
func Map(fn func( interface{} )) {
......
}
我不能这样调用它
Map(func(i int) {......})
因为 func(int)
类型与 func( interface{} )
类型不同。
但是当我定义 func( interface{} )
时,我的意思是任何类型的输入参数。如何在 Go 中实现这一点?
最佳答案
因为签名不匹配而失败。
当您调用 Println(3)
时,该函数不会将整数作为其第一个参数。而是将整数打包在 interface{}
变量中(自动转换,因为整数符合接口(interface)),然后将该变量传递给函数。这种转换发生在调用端,所以调用函数的过程不同于调用匹配func(i int)
的函数。
如果你想编写一个接受任意一元函数的函数,你需要声明它以一个 interface{}
变量作为它的参数,然后使用 reflect 检查值
包。 reflect
包还可以帮助你调用编译时不知道签名的任意函数。
例如:
func Map(f, v interface{}) interface{} {
fn := reflect.ValueOf(f)
fnType := fn.Type()
if fnType.Kind() != reflect.Func || fnType.NumIn() != 1 || fnType.NumOut() != 1 {
panic("Expected a unary function returning a single value")
}
res := fn.Call([]reflect.Value{reflect.ValueOf(v)})
return res[0].Interface()
}
这将使用参数 v
调用给定函数 f
并返回结果。如果 v
可分配给 f
的第一个参数,则调用将成功而不会出现 panic 。你可以在这里试验这个例子:http://play.golang.org/p/kkBu56JYb8
关于function - 函数类型中的空接口(interface){},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26135227/