【问题标题】:Is it possible to store a Type in a map and use it later to instantiate an object in Go lang? [duplicate]是否可以将类型存储在地图中并稍后使用它在 Go 语言中实例化对象? [复制]
【发布时间】:2017-08-24 18:23:06
【问题描述】:

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

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

有办法吗?

提前致谢。

【问题讨论】:

标签: go types


【解决方案1】:

您可以使用 reflect 包做到这一点,但应该注意的是,最终您必须知道具体类型才能真正使用它。

编辑:让我们知道。首先,这是一个非常糟糕的想法,如果您这样做,您可能应该重新考虑一下。 Go 是一种静态类型语言,除非你真的需要使用 reflect 包,否则你应该尽可能远离它。即便如此,在大多数情况下,这已经为您完成了。以 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)
}

【讨论】:

  • 谢谢。这非常有用。
  • 副本中的答案更好地解释了发生了什么。
猜你喜欢
  • 1970-01-01
  • 2015-07-17
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多