holdtom
有两种可能的方法。一种是通过反射,即reflect封装,特别是Call方法。第二个是通过函数值和闭包。我不会推荐第一个解决方案,通常不鼓励反射,因为它很复杂、容易出错并且成本高昂。通过反射解决方案(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() }
心有法竹
对于那些在 2023 年及以后遇到这种情况的人...如果您出于测试目的而搜索此内容,或者您可以保证所有函数都具有相同的参数签名,那么您可以大大简化:——注意!!!这并不能解决每个参数签名不同的OP问题。然后你必须使用更像已接受的答案的东西。但由于这是“golang 中的函数调度映射”的最佳答案之一,我认为这会很有用var dispatchMap = map[string]func(yourSignature type){ "Key": funcName, "AnotherKey": anotherFunc,}例如...使用它来创建一个调度映射,以便在公共包装器内进行表驱动测试,但测试是不同的,并且并不都使用相同的函数...func Something(t *testing.T) { value := "value" assert.Equal(t, value, "value", "Didnt Pass???")}func FailSomething(t *testing.T) { value := "nooo" assert.Equal(t, value, "value", "Supposed to fail!")}var testMap = map[string]func(t *testing.T){ "TestSomething": Something, "TestFailSomething": FailSomething,}func TestWrapper(t *testing.T) { t.Parallel() for name, testCommand := range testMap { t.Run(name, testCommand) }}