您无法通过函数名称获得函数,而这正是您想要做的。原因是,如果Go工具可以检测到未显式引用某个函数(因此无法访问该函数),则该函数甚至可能无法编译为可执行二进制文件。
具有功能注册表
一种执行所需操作的方法是在调用它们之前构建“功能注册表”:
registry := map[string]func(){ "MyFunc1": MyFunc1, "MyFunc2": MyFunc2, "MyFunc3": MyFunc3,}for k := 1; k <= 3; k++ { registry[fmt.Sprintf("MyFunc%d", k)]()}输出(在Go Playground上尝试):
Hello MyFunc1Hello MyFunc2Hello MyFunc3
手动“路由”
与注册表类似,它检查名称并手动路由到该函数,例如:
func callByName(name string) { switch name { case "MyFunc1": MyFunc1() case "MyFunc2": MyFunc2() case "MyFunc3": MyFunc3() default: panic("Unknown function name") }}使用它:
for k := 1; k <= 3; k++ { callByName(fmt.Sprintf("MyFunc%d", k))}在Go Playground上尝试一下。
注意:
由您决定是否要在
callByName()帮助函数中调用由其名称标识的函数,或者您可以选择返回一个函数值(类型为
func())并在调用者的位置调用它。
将函数转换为方法
还要注意,如果您的函数实际上是某种类型的 方法
,则可以在没有注册表的情况下进行操作。使用反射,您可以按名称获取方法:
Value.MethodByName()。您还可以使用
Value.NumMethod()和获取/枚举所有方法而无需知道它们的名称
Value.Method()(另请参见
Type.NumMethod()以及
Type.Method()是否需要该方法的名称或其参数类型)。
这是可以做到的:
type MyType intfunc (m MyType) MyFunc1() { fmt.Println("Hello MyFunc1")}func (m MyType) MyFunc2() { fmt.Println("Hello MyFunc2")}func (m MyType) MyFunc3() { fmt.Println("Hello MyFunc3")}func main() { v := reflect.ValueOf(MyType(0)) for k := 1; k <= 3; k++ { v.MethodByName(fmt.Sprintf("MyFunc%d", k)).Call(nil) }}输出是相同的。在Go Playground上尝试一下。



