2 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超5個(gè)贊
首先,您應(yīng)該始終檢查返回的錯(cuò)誤。bson.Marshal()
并bson.Unmarshal()
返回您不檢查的錯(cuò)誤。這樣做揭示了為什么它不起作用:
unmarshal 無法處理結(jié)構(gòu)值。使用指針
pt
是類型reflect.Value
(恰好是一個(gè)結(jié)構(gòu)),而不是你應(yīng)該傳遞給bson.Unmarshal()
.?例如,您應(yīng)該傳遞一個(gè)指向要解組的結(jié)構(gòu)值的指針(它將被包裝在一個(gè)interface{}
值中)。所以調(diào)用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)
}
(在你的真實(shí)代碼中你想做一些除了 panic 之外的事情,這只是為了表明你應(yīng)該總是檢查錯(cuò)誤?。?/p>
另請注意,可以將映射直接轉(zhuǎn)換為結(jié)構(gòu)(直接意味著無需編組和解組)。您可以手動(dòng)實(shí)施或使用現(xiàn)成的第 3 方庫。
另請注意,有更聰明的方法可以解決您想要做的事情。您可以將類型存儲(chǔ)在 ID 本身中,因此如果您有 ID,則可以構(gòu)造一個(gè)類型的值以解組到查詢結(jié)果中,這樣您就可以跳過整個(gè)過程。這會(huì)簡單得多,效率也高得多。
例如,您可以使用以下 ID 結(jié)構(gòu):
<type>-<id>
例如:
my.package.S1-123
獲取/加載此文檔時(shí),您可以使用反射來創(chuàng)建 的值my.package.S1
,并直接解組到該值(將其傳遞給Query.One()
)。

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超5個(gè)贊
這是一個(gè)getById()實(shí)際有效的修改版本:
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
}
從結(jié)構(gòu)到結(jié)構(gòu)的轉(zhuǎn)換由https://github.com/mitchellh/mapstructurebson.M處理,而不是 marshalling-unmarshaling。
- 2 回答
- 0 關(guān)注
- 210 瀏覽
添加回答
舉報(bào)