将字符串值转换为函数调用

时间:2016-03-26 19:05:01

标签: reflection go

我想基于字符串指定一个函数。我从地图中获取字符串,在下面的示例中,它们是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"))
}

1 个答案:

答案 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。