0

I am new to Go and I have this problem. I need to make a kind of "dispatcher" that will receive a string and return a type to be instantiated based on the string. For example:

AnimalType := mymap["animal"]
newAnimal := new(AnimalType)

Is there a way to do so?

Thanks in advance.

fhpriamo
  • 78
  • 1
  • 7

1 Answers1

2

You can do this with the reflect package, though it should be noted that eventually you have to know the concrete type to really do much with it.

EDIT: LET IT BE KNOWN. This is a very BAD idea in the first place, and if you are doing this, you should probably rethink things. Go is a statically typed language, and unless you REALLY need to use the reflect package, you should stay away from it if possible. Even then, in most cases, this has already been done for you. Take, for instance, the JSON Marshal/Unmarshaller. At its core, they do some nasty reflection stuff, but it is already taken care of for you, just use it.

It is important to note that the type assertions (the .(*Thing1) lines) will panic if it isn't the right type. See https://tour.golang.org/methods/15

Test on playground: https://play.golang.org/p/DhiTnCVJi1

package main

import (
    "fmt"
    "reflect"
)

type Thing1 bool

type Thing2 int

type Thing3 struct {
    Item string
}

func main() {
    m := map[string]reflect.Type{}
    var t1 Thing1
    var t2 Thing2
    var t3 Thing3
    m["thing1"] = reflect.TypeOf(t1)
    m["thing2"] = reflect.TypeOf(t2)
    m["thing3"] = reflect.TypeOf(t3)

    // later on

    // thing1
    newT1Value := reflect.New(m["thing1"])
    // you use * here because a pointer to a boolean type isn't useful
    newT1 := *newT1Value.Interface().(*Thing1) // cast to concrete type

    fmt.Printf("T1: %v\n", newT1)

    // thing2
    newT2Value := reflect.New(m["thing2"])
    // you use * here because a pointer to an int type isn't useful
    newT2 := *newT2Value.Interface().(*Thing2)

    fmt.Printf("T2: %v\n", newT2)

    // thing3
    newT3Value := reflect.New(m["thing3"])
    // you can choose to use * or not here. Pointers to structs are actually useful
    newT3 := newT3Value.Interface().(*Thing3)
    newT3.Item = "Hello world"

    fmt.Printf("T3: %#v\n", newT3)
}
RayfenWindspear
  • 6,116
  • 1
  • 30
  • 42