2 回答
TA贡献1851条经验 获得超5个赞
首先,您应该始终检查返回的错误。bson.Marshal()
并bson.Unmarshal()
返回您不检查的错误。这样做揭示了为什么它不起作用:
unmarshal 无法处理结构值。使用指针
pt
是类型reflect.Value
(恰好是一个结构),而不是你应该传递给bson.Unmarshal()
. 例如,您应该传递一个指向要解组的结构值的指针(它将被包装在一个interface{}
值中)。所以调用Value.Interface()
返回的值reflect.New()
:
pt := reflect.New(t).Interface()
您可以将其传递给bson.Unmarshal()
:
bsonBytes, err := bson.Marshal(m)
if err != nil {
panic(err)
}
if err = bson.Unmarshal(bsonBytes, pt); err != nil {
panic(err)
}
(在你的真实代码中你想做一些除了 panic 之外的事情,这只是为了表明你应该总是检查错误!)
另请注意,可以将映射直接转换为结构(直接意味着无需编组和解组)。您可以手动实施或使用现成的第 3 方库。
另请注意,有更聪明的方法可以解决您想要做的事情。您可以将类型存储在 ID 本身中,因此如果您有 ID,则可以构造一个类型的值以解组到查询结果中,这样您就可以跳过整个过程。这会简单得多,效率也高得多。
例如,您可以使用以下 ID 结构:
<type>-<id>
例如:
my.package.S1-123
获取/加载此文档时,您可以使用反射来创建 的值my.package.S1
,并直接解组到该值(将其传递给Query.One()
)。
TA贡献1810条经验 获得超5个赞
这是一个getById()实际有效的修改版本:
func getById(coll *mgo.Collection, id interface{}) (*I, error) {
// read wrapper
wrapper := Wrapper{}
err := coll.Find(bson.M{"_id": id}).One(&wrapper)
if err != nil {
return nil, err
}
// obtain Type from registry
t := typeregistry.GetType(wrapper.TypeKey)
// get a pointer to a new value of this type
pt := reflect.New(t)
// populate value using wrapper.Val
err = mapstructure.Decode(wrapper.V, pt.Interface())
if err != nil {
return nil, err
}
// return the value as *I
i := pt.Elem().Interface().(I)
return &i, nil
}
从结构到结构的转换由https://github.com/mitchellh/mapstructurebson.M处理,而不是 marshalling-unmarshaling。
- 2 回答
- 0 关注
- 155 浏览
添加回答
举报