Go语言 如何创建类型使用反射有指针接收器

rjee0c15  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(84)

我有两个任务结构,即ShellTaskCmdTask。创建了一个TaskExecutor接口,并在ShellTaskCmdTask指针接收器中实现了这些方法。并在运行时使用反射动态创建任务执行器。然而,当我在运行时运行程序时,得到错误消息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 link

5jvtdoz2

5jvtdoz21#

https://pkg.go.dev/[email protected]#Value.Elem
Elem返回接口v包含或指针v指向的值。如果v的Kind不是Interface或Pointer,则会出现异常。如果v为nil,则返回零值。
所以,如果你想要指针而不是指向的值,你需要删除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")
}

相关问题