Go 将结构转换为切片结构

Go 将结构转换为切片结构,go,struct,interface,reflect,Go,Struct,Interface,Reflect,我试图通过字符串输入选择一个struct,然后根据返回的JSON对象或数组,解组JSON。考虑一种将结构反映到切片结构的方法是否正确?如果是这样的话,如何通过反射来实现呢? 当做 彼得 展开我的评论,您可以创建一个工厂,在其中注册预定义类型: type Factory struct { m map[string]reflect.Type } func (f *Factory) Register(v interface{}) { vt := reflect.TypeOf(v)

我试图通过字符串输入选择一个struct,然后根据返回的JSON对象或数组,解组JSON。考虑一种将结构反映到切片结构的方法是否正确?如果是这样的话,如何通过反射来实现呢? 当做 彼得


展开我的评论,您可以创建一个工厂,在其中注册预定义类型:

type Factory struct {
    m map[string]reflect.Type
}

func (f *Factory) Register(v interface{}) {
    vt := reflect.TypeOf(v)
    n := vt.Name()
    f.m[n] = vt
    f.m["[]"+n] = reflect.SliceOf(vt) // implicitly register a slice of type too
}
这些类型可以在运行时按名称查找,并使用JSON数据初始化:

使用:

type Place struct {
    City string `json:"city"`
}

factory.Register(Place{})

p, err := factory.Make("Place", []byte(`{"city":"NYC"}`))

fmt.Printf("%#v\n", p) // &main.Place{City:"NYC"}
切片也起作用:

ps, err := factory.Make("[]Place", []byte(`[{"city":"NYC"},{"city":"Dublin"}]`))

fmt.Printf("%#v\n", p, p) // &[]main.Place{main.Place{City:"NYC"}, main.Place{City:"Dublin"}}

游乐场:

这似乎不是个好主意,你有没有特别想解决的问题?例如,在您的代码中,使用该语言提供的初始化原语的具体优势是什么?e、 我有大约50个结构。这将在“getModelByName”函数中提供100行代码。我认为有一个更好的方法…我试图解决的问题是,有时我会返回一个对象json,有时会返回一个指向同一个结构的数组json来解组。如果你真的需要对返回的returnModel做一些有意义的事,你必须键入assert这个值,在我看来,完全违背了getModelByName的目的。我认为getModelByName方法只有在您不太关心底层类型的情况下才有意义,您只需要将数据以另一种格式传递到某个地方,例如,将json转换为xml。我试图实现的是,我需要解组大约50个api端点。e、 g.1端点可以返回带有字段的json对象,同一端点有时可以返回带有相同对象字段的数组。因此,如果它是一个对象,我可以将其解组为一个名称结构,如果它是一个数组,我可以将其解组为一个[]名称结构,但我不想声明两个结构,因为它们包含相同的字段。@mkopriva ah-认为可以在包级别执行此操作-看起来只有从特定的结构值或其本机字段开始时才可能。我想注册函数是实现这一点的最简单的方法。更新的答案隐式支持注册类型的切片。
type Place struct {
    City string `json:"city"`
}

factory.Register(Place{})

p, err := factory.Make("Place", []byte(`{"city":"NYC"}`))

fmt.Printf("%#v\n", p) // &main.Place{City:"NYC"}
ps, err := factory.Make("[]Place", []byte(`[{"city":"NYC"},{"city":"Dublin"}]`))

fmt.Printf("%#v\n", p, p) // &[]main.Place{main.Place{City:"NYC"}, main.Place{City:"Dublin"}}