英文:
Convert string value to function call
问题
我想根据一个字符串来指定一个函数。我从一个映射中获取字符串,在下面的示例中,它们是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"))
}
英文:
I want to specify a function based on a string. I'm getting strings out of a map, in the example below they are the values in function
while interating ove the map. Now for example, when the string value function
== "networkInfo", I would like to "treat" that value as a real functions' name. It's hard to explain, but I think you guys will know what I mean.
My goal is to remove the switch statement and directly call c.AddFunc(spec, func() { networkInfo() })
where networkInfo is the function name, extracted from string function
. I know this is possible, but I don't know how :(. Help is appreciated!
// 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"))
}
答案1
得分: 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() }) // 不确定是否需要封闭的函数
} else {
log.Errorf("unknown task: %q", function)
}
}
如果你需要函数的签名有所不同,那么你实际上需要使用反射,但如果函数的类型都相同,那么使用这种映射的方法可能是一个更简单的解决方案,而且没有反射的开销。
我发现在一个包中按名称查找函数的唯一方法是通过解析源文件。这个仓库是一个将函数找到并存储在以名称为键的映射中的示例。
Go链接器会静默丢弃未被引用的函数,所以如果你通过反射是唯一引用函数的方式,那么它将会失效。这就是为什么我建议使用映射方法更好,它可以让链接器知道函数正在被使用。
英文:
Why not something like:
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)
}
}
If you do need varying signatures of your funcs then you'd actually need reflection, but if the types of the funcs are all the same, then using this map approach might be a simpler solution, without the overhead of reflection.
The only way I've found to find functions by name in a package is by actually parsing the source files. This repo is an example of finding funcs and storing them in a map with the name as the key.
The Go linker will silently drop unreferenced funcs, so if the only way you're referencing the func is through reflection it would break. That is why the map approach I suggest is superior; it let's the linker know the func is being used.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论