英文:
Run function from a package by reflecting its name
问题
目前我将包名作为字符串"Forecast"
,我需要将这个字符串反映到一个包中,以便我可以调用函数Run()
。有没有办法实现这种反射?
为什么?
目前我正在使用golang构建一个任务运行器,其中所有任务都有函数Run()
,我通过kafka消息"task": "Forecast"
接收要运行的任务,所以我试图避免使用switch
语句,像这样:
switch message.Task {
case "Forecast":
Forecast.Run()
case "SupplyCalculator":
SupplyCalculator.Run()
}
而是通过反射来动态调用函数,类似于这样(PHP):
$task = new ReflectionClass("\\Task\\{$message->task}");
$task->run();
英文:
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();
答案1
得分: 4
在Go语言中,包(Packages)不是一种类型。
给定一个名为foo
的包,其中包含一个名为Run
的函数,以下代码是有效的:
v := reflect.ValueOf(foo.Run)
fmt.Println(v.Kind()) // func
但是以下代码会导致语法错误:
v := reflect.ValueOf(foo)
不要试图使用反射,而是在一个映射(map)中提前注册函数,然后在该映射中查找正确的函数并调用它。你可以提供一个简单的tasks
包来实现这一点,其中包含Register
和Run
等方法。
// tasks.go
package tasks
type TaskFunc func() error // 或者根据你的任务需要传入的参数定义
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)
英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论