我有两个任务结构,即 ShellTask
和 CmdTask
。创建了 TaskExecutor
接口并实现了 ShellTask
和 CmdTask
指针接收器中的方法。并在运行时使用反射动态创建任务执行器。但是,当我在运行时运行程序时收到消息 panic: interface conversion: main.ShellTask is not main.TaskExecutor: Missing method Run
错误,但是,如果我将指针接收器更改为非指针接收器,事情就会开始工作。
如何创建带有指针的对象,以便指针接收器工作。
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 链接
正确答案
https://pkg.go.dev/[电子邮件受保护]#Value.Elem
因此,如果您想要指针而不是指向的值,则需要删除 e := newPtr.Elem()
步骤。
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")
}