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 之外的事情,這只是為了表明你應該總是檢查錯誤?。?/p>
另請注意,可以將映射直接轉換為結構(直接意味著無需編組和解組)。您可以手動實施或使用現成的第 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 關注
- 214 瀏覽
添加回答
舉報