我的代码类似于以下
package main
import "fmt"
func PrintThis(arg string) {
fmt.Printf("I'm printing %s", arg)
}
func PrintThisAndThat(arg1, arg2 string) {
fmt.Printf("Now printing %s and %s", arg1, arg2)
}
func Invoke(fn interface{}, args ...string) {
//fn(args...)
}
func main() {
Invoke(PrintThis, "foo")
Invoke(PrintThisAndThat, "foo", "bar")
}
这不是实际的生产代码,但这是一个简化版本。
问题: - 如果我取消注释行//fn(args...)
,我收到编译错误prog.go:14: cannot call non-function fn (type interface {})
如何执行Invoke()函数作为参数接收的函数?
实现这一目标的正确方法是什么?
答案 0 :(得分:6)
您可以使用reflect.Value
的{{3}}或Call
方法将其称为函数。与所有reflect.Value
方法一样,此恐慌是fn
类型错误。
func Invoke(fn interface{}, args ...string) {
v := reflect.ValueOf(fn)
rargs := make([]reflect.Value, len(args))
for i, a := range args {
rargs[i] = reflect.ValueOf(a)
}
v.Call(rargs)
}
答案 1 :(得分:3)
您可以使用类似http://play.golang.org/p/opotbIGdrA
的类型开关package main
import "fmt"
func PrintThis(arg string) {
fmt.Printf("I'm printing %s", arg)
}
func PrintThisAndThat(arg1, arg2 string) {
fmt.Printf("Now printing %s and %s", arg1, arg2)
}
func Invoke(fn interface{}, args ...string) {
switch m := fn.(type) {
case func(string):
m(args[0])
case func(string, string):
m(args[0], args[1])
default:
}
}
func main() {
Invoke(PrintThis, "foo")
Invoke(PrintThisAndThat, "foo", "bar")
}
但您需要知道将传递哪些函数才能使其正常工作。
顺便说一句,您可以使用PrintThis
而不是多个字符串参数将...string
转换为可变参数函数。
答案 2 :(得分:0)
您需要将参数fn
声明为函数,而不是interface{}
。 fn(args...)
如何适用于PrintThis
,有一个参数,还有PrintThisAndThat
,有两个参数?您需要确定要接收的函数类型,并将其声明为参数。