可以将任何类型的对象分配给空接口。例如,我们有以下功能
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{} )
时,我的意思是任何类型的输入参数。我怎样才能在Golang中实现这一目标?
答案 0 :(得分:12)
失败,因为签名不匹配。
当您调用Println(3)
时,该函数不会将整数作为其第一个参数。而是整数被打包在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()
}
这将使用参数f
调用给定函数v
并返回结果。如果v
可分配给f
的第一个参数,则呼叫将成功而不会出现恐慌。您可以在此处试验此示例:http://play.golang.org/p/kkBu56JYb8
答案 1 :(得分:1)
我确实意识到它是一个古老的讨论,但是遇到了这个帖子,并且想尝试一下在另一个函数而不是func (interface{})
中包含任意函数interface{}
的概念。
通过提供可以接受interface{}
的函数的内联实现,我可以编写一个简单的实现。我们可以从另一个函数中调用该函数
varForGenFunc := func(in interface{}) int {
fmt.Println("type of this object: ",reflect.TypeOf(in))
return 1}
TakeGenericFunc(varForGenFunc, variableForGen)
通过此操作,我们可以编写func(interface{})
的任何实现并将其作为参数传递给TakeGenericFunc
您可以在此处试用它: