function - 函数类型中的空接口(interface){}

标签 function interface go

任何类型的对象都可以分配给空接口(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/

相关文章:

c# - 我不明白基类的继承

go - 从包的 godoc 引用不同的包

go - 是否应该在每个 CRUD 方法中打开和关闭数据库连接?

swift - 如何通过发送者以外的标签调用特定的UIButton?

java - Jersey REST/JAXB 错误,映射接口(interface)

c++ - 使用 FLTK 和 C++ : Making a function that fits an image within a defined frame

interface - Dart,是否可以隐式传递接口(interface)的成员?

google-app-engine - 如何使 golang gin 与谷歌应用程序引擎一起工作?

c++ - rbegin 和 rend() 在这个函数中做了什么?

python - 了解 Python 风格,函数的默认参数