根据字符串动态创建对象

时间:2018-10-22 06:26:32

标签: go reflection

我正在尝试根据字符串动态创建结构。

在下面的示例中,reflect.TypeOf&c和&c1不同,因为我从makeInstance返回interface {}。 TypeOf c和c1相同。

我的问题是我该如何更改处理makeInstance的输出的方式,以便它创建与c1相同的对象,但仍然允许我也创建与b1相同的对象?

type Car struct {
    Make  int `json:"make"`
    Model int `json:"model"`
}

type Bus struct {
    Seats int `json:"seats"`
    Route int `json:"route"`
}

var typeRegistry = make(map[string]reflect.Type)

func init() {
    typeRegistry["Car"] = reflect.TypeOf(Car{})
    typeRegistry["Bus"] = reflect.TypeOf(Bus{})

}

func makeInstance(name string) interface{} {
    v := reflect.New(typeRegistry[name]).Elem()

    return v.Interface()
}

func main() {

    c := makeInstance("Car")
    b := makeInstance("Bus")

    var b1 Bus
    var c1 Car

    fmt.Println(reflect.TypeOf(&c))
    fmt.Println(reflect.TypeOf(&c1))
    fmt.Println(reflect.TypeOf(c))  
    fmt.Println(reflect.TypeOf(c1))

编辑:

我的总体结果是拥有一个程序,该程序读取json配置文件,该文件将列出我要关闭并击中rest api并收集例如的对象的类型。

{
    "auth":[{
                "username": "admin",
                "password": "admin"
            }],
    "transport":[
            {
                "vehicle":["car", "bus"]
            }]
}

在车辆上循环时,它将命中一个api并执行查询并返回数据。然后,我想创建配置中包含的任何车辆的数组,然后将json响应解组到其中。我正在尝试动态创建对象,因此我可以避免不得不检查Vehicle = car,vehicle = bus等,因为我最终将拥有许多类型的车辆,但可能并不总是拥有所有车辆,而且似乎缠绵长。

2 个答案:

答案 0 :(得分:2)

该函数返回所写类型CarBus的值。如果希望main中的变量具有特定类型,请使用类型断言:

c := makeInstance("Car").(Car)

如果您的目标是获取这些类型的值的指针,请从makeInstance返回指针:

func makeInstance(name string) interface{} {
    return reflect.New(typeRegistry[name]).Interface()
}

答案 1 :(得分:1)

您可能应该停止阅读有关接口值类型断言的信息。 Go不是动态类型的语言,您尝试执行的操作很有可能失败:

只要您与interface{}一起使用,您就<​​em>不能直接访问字段(“制造”,“模型”,“座位”,“路线” ...),而无需进行反射。如果要编写x.Make,则必须使用xCar类型的*Car(而不是接口{})。

要从类型为c的{​​{1}}到例如您{em>必须输入断言的interface{}

Car

请注意,您无法进行动态类型声明(无反射),并且var car Car = c.(Car) 将在c包含以下内容时失败: c.(Car)。因此,在将json.Unmarshaling到通用接口{}之后,您将不得不打开已知类型并断言为该类型。这意味着您无论如何都要为每种类型编写专用代码。