根据map [string] somestruct调用golang调度方法 [英] golang dispatch method call according to a map[string]somestruct
问题描述
假设我有很多带有接收器的函数或方法,每个函数或方法都有不同类型的参数.我想使用表驱动的方法来调度函数或方法调用.因此,我将构建一个像这样的表:
Assuming I have lots of functions or methods with receiver, each of which has different type of parameters. I want to use table-driven method to dispatch function or method call. So I'll construct a table like this:
type command struct {
name string
handler func(parameter ...interface{}) // I don't know whether to use `...interface{}` is correct
}
table := map[string]command { ... }
func (c command)foo(f1 int, f2 string) {}
func (c command)bar(b1 bool, b2 int, b3 string) {}
// methods and so on
无论我收到什么命令,我将始终使用诸如 table [some-command-name](parameter1,parameter2,...)
之类的一条语句,而不要使用难看的switch-case结构.
No matter what command I receive, I'll always use one statement like table[some-command-name](parameter1, parameter2, ...)
instead of using the ugly switch-case structure.
这可能吗?难道不同的方法有不同数量的参数是一个问题吗?
Is this possible ? That different methods have different number of parameters is a problem ?
推荐答案
有两种可能的方法.一种是通过反射,即 reflect
包,尤其是 Call
方法.第二个是通过函数值和闭包.我不推荐第一种解决方案,通常不建议使用反射,因为它很复杂,容易出错并且价格昂贵.
There are two possible ways. One is through reflection, that is reflect
package and in particular the Call
method. The second one is through function values and closures. I would not recommend the first solution, reflection is generally discouraged because it is complicated, error prone and expensive.
反思解决方案( https://play.golang.org/p/3b5I77QMsFI ):
type command struct {
name string
handler reflect.Value
args []reflect.Value
}
var table = map[string]command{
"Foo": {
name: "Foo",
handler: reflect.ValueOf(foo),
args: []reflect.Value{
reflect.ValueOf(1),
reflect.ValueOf("hello"),
},
},
"Bar": {
name: "Bar",
handler: reflect.ValueOf(bar),
args: []reflect.Value{
reflect.ValueOf(true),
reflect.ValueOf(5),
reflect.ValueOf("hello"),
},
},
}
func foo(f1 int, f2 string) {
fmt.Println("Foo:", f1, f2)
}
func bar(b1 bool, b2 int, b3 string) {
fmt.Println("Bar:", b1, b2, b3)
}
func main() {
for name, command := range table {
fmt.Println("Running", name)
command.handler.Call(command.args)
}
}
通过函数闭包( https://play.golang.org/p/8fM86lxalq1):
type MyFuncType func()
type command struct {
name string
handler MyFuncType
}
var table = map[string]command{
"Foo": {
name: "Foo",
handler: fooClosure(1, "hello"),
},
"Bar": {
name: "Bar",
handler: barClosure(true, 5, "hello"),
},
}
func foo(f1 int, f2 string) {
fmt.Println("Foo:", f1, f2)
}
func fooClosure(f1 int, f2 string) MyFuncType {
return func() {
foo(f1, f2)
}
}
func bar(b1 bool, b2 int, b3 string) {
fmt.Println("Bar:", b1, b2, b3)
}
func barClosure(b1 bool, b2 int, b3 string) MyFuncType {
return func() {
bar(b1, b2, b3)
}
}
func main() {
for name, command := range table {
fmt.Println("Running", name)
command.handler()
}
}
这篇关于根据map [string] somestruct调用golang调度方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!