我有一个对象列表(确切地说是 olievere/Elastic SearchResult.Hits)。其中每个都有一个 json.RawMessage 对象,我希望创建一个可抽象的方法,该方法接受任何结构的接口(interface) slice ,Unmarshal 的每个单独的命中' json.RawMessage 。 > 到所述结构中,并将其附加到传入的 []interface
中。
这个函数不应该对所需的业务层结构有任何逻辑或洞察力,并且数据库调用的接口(interface)相当多,因此对上面提到的 Elastic 包没有可见性。我试图做的示例...
foo.go
import (bar, package)
type TestStruct struct {
Slice []*package.Struct // package.Struct has a value of Source which is a
// json.RawMessage
}
func GetData() bar.Test {
return &TestStruct{*package.GetData()}
}
func (result TestStruct) UnmarshalStruct(v []interface{}) {
for _, singleStruct := range result.Slice {
append(json.Unmarshal(singleStruct, &v))
}
第二个文件
bar.go
type Handler interface {
GetData() Test
}
type Test interface {
UnmarshalStruct
}
type OtherType struct {
foo string
bar string
}
func RetrieveData() []OtherType {
handler := New(Handler)
test := handler.GetData()
var typeSlice []OtherType
test.UnmarshalStruct(&typeSlice)
}
我希望将 []OtherType
类型的内容或我决定创建的任何其他新结构交给 UnmarshalStruct
,并让它返回对我来说同样的结构,只是充满了数据
例如,我将从 Elastic 中搜索两种不同类型的数据。我将收到以下两个对象之一的列表。
{ 'foo': '',
'id':
}
并且在不同的索引中
{ 'bar': '',
'baz': '',
'eee': ''
}
其中每一个自然都需要两个不同的结构。
但是,我希望有一种方法能够解码这些列表中的任何一个。我将在下面给出,并使用相同的函数,我希望能够将其转换为 bar
结构,并将其他类型转换为 foo
结构。
{ 'source': [
{ 'bar': '',
'baz': '',
'eee': ''
},
{ 'bar': '',
'baz': '',
'eee': ''
},
{ 'bar': '',
'baz': '',
'eee': ''
}
]
}
最佳答案
不经过反射(reflection),真的没有办法做你想做的事。我个人会以不同的方式构建它,以便您解码为更通用的类型,例如 map[string]string
,或者如 @ThunderCat 所示,摆脱中间状态并直接解码为正确的类型。但这是可以做到的...
(我将 json.RawMessage 直接移到 TestStruct 中,以消除一级间接性并使示例更加清晰)
type TestStruct struct {
Slice []json.RawMessage
}
func (t TestStruct) UnmarshalStruct(v interface{}) error {
// get the a Value for the underlying slice
slice := reflect.ValueOf(v).Elem()
// make sure we have adequate capacity
slice.Set(reflect.MakeSlice(slice.Type(), len(t.Slice), len(t.Slice)))
for i, val := range t.Slice {
err := json.Unmarshal(val, slice.Index(i).Addr().Interface())
if err != nil {
return err
}
}
return nil
}
然后你就可以这样调用它
var others []OtherType
err := ts.UnmarshalStruct(&others)
if err != nil {
log.Fatal(err)
}
关于Golang抽象Interface Slice转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29400044/