Home > Mobile >  Run function from a package by reflecting its name
Run function from a package by reflecting its name

Time:10-28

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)
  •  Tags:  
  • go
  • Related