我正在尝试根据字符串动态创建结构。
在下面的示例中,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等,因为我最终将拥有许多类型的车辆,但可能并不总是拥有所有车辆,而且似乎缠绵长。>
答案 0 :(得分:2)
该函数返回所写类型Car
和Bus
的值。如果希望main
中的变量具有特定类型,请使用类型断言:
c := makeInstance("Car").(Car)
如果您的目标是获取这些类型的值的指针,请从makeInstance
返回指针:
func makeInstance(name string) interface{} {
return reflect.New(typeRegistry[name]).Interface()
}
答案 1 :(得分:1)
您可能应该停止阅读有关接口值类型断言的信息。 Go不是动态类型的语言,您尝试执行的操作很有可能失败:
只要您与interface{}
一起使用,您就<em>不能直接访问字段(“制造”,“模型”,“座位”,“路线” ...),而无需进行反射。如果要编写x.Make
,则必须使用x
或Car
类型的*Car
(而不是接口{})。
要从类型为c
的{{1}}到例如您{em>必须输入断言的interface{}
:
Car
请注意,您无法进行动态类型声明(无反射),并且var car Car = c.(Car)
将在c包含以下内容时失败: c.(Car)
。因此,在将json.Unmarshaling到通用接口{}之后,您将不得不打开已知类型并断言为该类型。这意味着您无论如何都要为每种类型编写专用代码。