我想基于字符串指定一个函数。我从地图中获取字符串,在下面的示例中,它们是function
中的值,同时在地图上进行交互。现在例如,当字符串值function
==" networkInfo"时,我想"对待"这个价值作为一个真正的功能'名称。这很难解释,但我想你们都会知道我的意思。
我的目标是删除switch语句并直接调用c.AddFunc(spec, func() { networkInfo() })
,其中networkInfo是函数名,从字符串function
中提取。我知道这是可能的,但我不知道如何:(。感谢帮助!
// ScheduleCronjobs starts the scheduler
func ScheduleCronjobs() {
tasks := props.P.GetStringMapString("tasks")
log.Infof("number of tasks: %d", len(tasks))
if len(tasks) != 0 {
c := cron.New()
// for each task, initialize
for function, spec := range tasks {
switch function {
case "networkInfo":
c.AddFunc(spec, func() { networkInfo() })
case "bla":
c.AddFunc(spec, func() { bla() })
default:
log.Errorf("unknown task: %q", function)
}
}
c.Start()
}
// after initialization, send out confirmation message
slack.SendMessage("tasks initialized", props.P.GetString("channel"))
}
答案 0 :(得分:3)
为什么不能这样:
taskDefs := map[string]func(){
"networkInfo": networkInfo,
"bla": bla,
}
for function, spec := range tasks {
if fn, ok := taskDefs[function]; ok {
c.AddFunc(spec, func() { fn() }) // not sure if you need the enclosing func
} else {
log.Errorf("unknown task: %q", function)
}
}
如果你确实需要改变你的funcs的签名,那么你实际上需要反射,但如果funcs的类型都是相同的,那么使用这种map方法可能是一个更简单的解决方案,没有反射的开销
我发现在程序包中按名称查找函数的唯一方法是实际解析源文件。 This repo是一个查找func并将其存储在名称为键的地图中的示例。
Go链接器将以静默方式删除未引用的func,因此如果您引用func的唯一方法是通过反射它将会中断。这就是我建议的地图方法优越的原因;它让链接器知道正在使用func。