我有一个名为“seeder”的软件包:
package seeder
import "fmt"
func MyFunc1() {
fmt.Println("I am Masood")
}
func MyFunc2() {
fmt.Println("I am a programmer")
}
func MyFunc3() {
fmt.Println("I want to buy a car")
}
现在我想用MyFunc前缀调用所有函数
package main
import "./seeder"
func main() {
for k := 1; k <= 3; k++ {
seeder.MyFunc1() // This calls MyFunc1 three times
}
}
我想要这样的东西:
for k := 1; k <= 3; k++ {
seeder.MyFunc + k ()
}
这个输出:
EDIT1 :
在此示例中,parentKey是在循环中更改的字符串变量
for parentKey, _ := range uRLSjson{
pppp := seeder + "." + strings.ToUpper(parentKey)
gorilla.HandleFunc("/", pppp).Name(parentKey)
}
但是GC说:
最佳答案
您无法通过函数名称获得函数,而这正是您想要做的。原因是,如果Go工具可以检测到未显式引用某个函数(因此无法访问该函数),则该函数甚至可能无法编译为可执行二进制文件。有关详细信息,请参见Splitting client/server code。
具有功能注册表
一种执行所需操作的方法是在调用它们之前构建“功能注册表”:
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 MyFunc1
Hello MyFunc2
Hello 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()
helper函数中调用由其名称标识的函数,或者您可以选择返回一个函数值(类型为func()
)并在调用者的位置调用它。将函数转换为方法
还要注意,如果您的函数实际上是某种类型的方法,则可以在没有注册表的情况下进行操作。使用反射,您可以按名称获取方法:
Value.MethodByName()
。您也可以使用 Value.NumMethod()
和 Value.Method()
获取/枚举所有方法而无需知道它们的名称(如果需要方法的名称或其参数类型,请参见Type.NumMethod()
和Type.Method()
)。这是可以做到的:
type MyType int
func (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上尝试一下。