是否可以在地图中存储Type并稍后使用它来实例化Go lang中的对象?

时间:2017-03-30 17:18:01

标签: go types

我是Go的新手,我遇到了这个问题。我需要创建一种“调度程序”,它将接收一个字符串并返回一个基于字符串实例化的类型。例如:

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

有办法吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

您可以使用reflect包执行此操作,但应注意最终您必须知道具体类型才能真正做到这一点。

编辑:让我们知道。这首先是一个非常糟糕的想法,如果你这样做,你应该重新思考一下。 Go是一种静态类型语言,除非您真的需要使用反射包,否则应尽可能远离它。即便如此,在大多数情况下,这已经为您完成了。以JSON Marshal / Unmarshaller为例。在它的核心,他们做了一些讨厌的反思,但它已经为你照顾,只需使用它。

重要的是要注意,如果类型断言(.(*Thing1)行)不是正确的类型,它将panic行。见https://tour.golang.org/methods/15

在操场上测试: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)
}