I have two task structures, namely ShellTask
and CmdTask
. Created the TaskExecutor
interface and implemented the methods in the ShellTask
and CmdTask
pointer receivers. And use reflection to dynamically create task executors at runtime. However, when I run the program at runtime I get the message panic: interface conversion: main.ShellTask is not main.TaskExecutor: Missing method Run
error, however, if I change the pointer receiver to non-pointer receiver and things will start working.
How to create an object with a pointer so that pointer receivers work.
package main import ( "errors" "fmt" "reflect" ) type Task struct { Name string } type TaskExecutor interface { Run() error } type ShellTask struct { *Task } func (t *ShellTask) Run() error { fmt.Println("Running linux task") return nil } type CmdTask struct { *Task } func (t *CmdTask) Run() error { fmt.Println("Running linux task") return nil } var registry = make(map[string]reflect.Type) func Register(moduleName string, v interface{}) { registry[moduleName] = reflect.TypeOf(v) } func GetTaskExecutor(name string) (TaskExecutor, error) { if k, ok := registry[name]; ok { newPtr := reflect.New(k) e := newPtr.Elem() f := e.Interface().(TaskExecutor) return f, nil } return nil, errors.New("no task handler found") } func main() { Register("cmd", CmdTask{}) Register("shell", ShellTask{}) exec, err := GetTaskExecutor("shell") if err != nil { panic(err) } exec.Run() }
Go Playground Link
https://pkg.go.dev/[email protected]#Value.Elem
So if you want the pointer instead of the value pointed to, you need to remove the e := newPtr.Elem()
step.
func GetTaskExecutor(name string) (TaskExecutor, error) { if k, ok := registry[name]; ok { p := reflect.New(k) f := p.Interface().(TaskExecutor) return f, nil } return nil, errors.New("no task handler found") }
The above is the detailed content of How to create a type using reflection with pointer receiver. For more information, please follow other related articles on the PHP Chinese website!