Home  >  Article  >  Backend Development  >  How to create a type using reflection with pointer receiver

How to create a type using reflection with pointer receiver

王林
王林forward
2024-02-06 08:45:071077browse

How to create a type using reflection with pointer receiver

Question content

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


Correct Answer


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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete