Currently I have the package name as a string "Forecast"
and I need to reflect this string into a package so that I can call the function Run()
. Is there a way to make this reflection?
Why?
Currently I am building a task runner in golang in which all tasks have the function Run()
and I receive which task to run by a kafka message "task": "Forecast"
, so I am trying to avoid a switch
like:
switch message.Task {
case "Forecast":
Forecast.Run()
case "SupplyCalculator":
SupplyCalculator.Run()
}
And instead to just reflect the name and call the function, like this (PHP):
$task = new ReflectionClass("\\Task\\{$message->task}");
$task->run();
CodePudding user response:
Packages are not a type in Go.
Given a package foo
with a function Run
, this works...
v := reflect.ValueOf(foo.Run)
fmt.Println(v.Kind()) // func
But this is a syntax error:
v := reflect.ValueOf(foo)
Instead of trying to use reflection, register the functions ahead of time in a map, and then look up the correct function in that map to call it. You can provide a simple tasks
package to do this, with methods like Register
and Run
.
// 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)
}
// forecast.go
package forecast
import "tasks"
tasks.Register("forecast", Run)
func Run() error {
// ...
}
// main.go
err := tasks.Run(message.Task)