函数类型中的Golang空接口{}

时间:2014-10-01 06:18:49

标签: function interface go

可以将任何类型的对象分配给空接口。例如,我们有以下功能

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中实现这一目标?

2 个答案:

答案 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

您可以在此处试用它:

https://play.golang.org/p/f5UUhyhEx7u