通过反映包的名称来运行包中的函数

Mat*_*ann 1 go

目前,我将包名称作为字符串"Forecast",我需要将该字符串反映到包中,以便我可以调用该函数Run()。有没有办法进行这种反思?

为什么?

目前我正在 golang 中构建一个任务运行程序,其中所有任务都具有该功能Run(),并且我通过 kafka 消息接收要运行的任务"task": "Forecast",所以我试图避免switch类似的情况:

switch message.Task {
  case "Forecast":
    Forecast.Run()
  case "SupplyCalculator":
    SupplyCalculator.Run()
}
Run Code Online (Sandbox Code Playgroud)

而只是反映名称并调用函数,如下所示(PHP):

$task = new ReflectionClass("\\Task\\{$message->task}");
$task->run();
Run Code Online (Sandbox Code Playgroud)

mea*_*gar 5

包不是 Go 中的类型。

foo给定一个带有 function 的包Run,这有效......

v := reflect.ValueOf(foo.Run)
fmt.Println(v.Kind()) // func
Run Code Online (Sandbox Code Playgroud)

但这是一个语法错误:

v := reflect.ValueOf(foo)
Run Code Online (Sandbox Code Playgroud)

不要尝试使用反射,而是提前在映射中注册函数,然后在该映射中查找正确的函数来调用它。您可以提供一个简单的包来执行此操作,使用和tasks等方法。RegisterRun

// tasks.go
package tasks

type TaskFunc func() error // or whatever arguments your tasks take
var taskFuncs = map[string]TaskFunc{}

func Register(name string, fn TaskFunc) {
  taskFuncs[name] = fn
}

func Run(name string) error {
  if fn, found := taskFuncs[name]; found {
    return fn()
  }
  return fmt.Errorf("Task %q not found", name)
}
Run Code Online (Sandbox Code Playgroud)
// forecast.go
package forecast

import "tasks"

tasks.Register("forecast", Run)

func Run() error {
   // ...
}

Run Code Online (Sandbox Code Playgroud)
// main.go

err := tasks.Run(message.Task)
Run Code Online (Sandbox Code Playgroud)