英文:
Invoke a function which is received as an interface variable in golang
问题
我有一个类似以下代码的代码:
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() 函数的函数?
实现这一目标的正确方法是什么?
英文:
I have a code which is similar to the following
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")
}
This is not the actual production code, but this is a simplified version.
Question :- If I uncomment the line //fn(args...)
I get a compile error prog.go:14: cannot call non-function fn (type interface {})
How do I execute the function which is received as the argument tho the Invoke() function?
What is the right way to achieve this?
答案1
得分: 9
你可以使用reflect.Value
的Call
或CallSlice
方法将其作为函数进行调用。与所有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)
}
你可以在这里查看示例代码:http://play.golang.org/p/xGmNLDcLL_
英文:
You use the Call
or CallSlice
methods of the reflect.Value
to call it as a function. As with all reflect.Value
methods, this panics is fn
is the wrong type.
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)
}
答案2
得分: 5
你可以像这样使用类型开关:http://play.golang.org/p/opotbIGdrA
package main
import "fmt"
func PrintThis(arg string) {
fmt.Printf("我正在打印 %s", arg)
}
func PrintThisAndThat(arg1, arg2 string) {
fmt.Printf("现在打印 %s 和 %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")
}
但是你需要知道将要传递的函数,以使其正常工作。
顺便说一下,你可以通过使用...string
而不是多个字符串参数将PrintThis
转换为可变参数函数。
英文:
You can use a type switch like so 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")
}
But you kind of need to know what functions will be passed to make this work properly.
Btw you can turn PrintThis
into a variadic function by using ...string
instead of multiple string arguments.
答案3
得分: -1
你需要将参数fn
声明为一个函数,而不是interface{}
。对于只有一个参数的PrintThis
和有两个参数的PrintThisAndThat
,fn(args...)
应该如何工作?你需要决定你想要接收的函数类型,并将其声明为参数。
英文:
You need to declare the parameter fn
as a function, not as interface{}
. How is fn(args...)
supposed to work for PrintThis
, with one argument, and also with PrintThisAndThat
, with two arguments? You need to decide which type of function you want to receive and declare that as the parameter.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论