gpt4 book ai didi

go - 如何使用 bson.SetBSON 或 bson.Raw?

转载 作者:行者123 更新时间:2023-12-01 22:24:21 31 4
gpt4 key购买 nike

可能相关:How to use interface type as a model in mgo (Go)?

我有一个像这样的结构:

type Game struct {
ID bson.ObjectId
Type string
Location string
Details interface{}
}

type FeudDetails struct {
...
}

type TriviaDetails struct {
...
}

type BingoDetails struct {
...
}

我想用 Type领域 Game反序列化 Details转换为特定类型(例如 FeudDetailsBingoDetails 的实例)。它仍然是 interface{}Game ,但后来我可以这样做:
feudDetails, ok := game.Details.(FeudDetails)
if ok {
// we know this is a Feud game, and we have the details
feudDetails.Round++
}

The docs使用 bson.Raw 说“可以部分解码或编码值” ,但他们没有提供我能找到的任何例子。

我试过使用:
func (game *Game) SetBSON(r bson.Raw) error {
err := r.Unserialize(game)
if err != nil {
return nil
}
games[game.Type].LoadDetails(game) // this calls a function based on the Type to
// create a concrete value for that game.
return nil
}

我在这里得到一个(咳咳)堆栈溢出。我认为这是因为 r.Unserialize正在递归调用 SetBSON .

我的目标是对除 Details 之外的所有字段使用标准反序列化,然后就可以使用 game.Type确定如何处理 Details .如果我做这样的事情:
type GameDetails interface{}

type Game struct {
...
Details GameDetails
}

func (details *GameDetails) SetBSON(r bson.Raw) error {
// game isn't defined
games[game.Type].LoadDetails(r, details)
}

那么我如何访问外部 Type字段知道将其反序列化为哪种游戏类型?

我也会接受答案“你做错了,Go 中更好的模式是 XYZ ......”

编辑:我也尝试过正常反序列化,然后转换 interface{} Details 的版本使用 game.Details.(FeudDetails) ,但转换失败。我想我不能那样做,因为反序列化后的底层类型不是 FeudDetails但很可能 map[string]interface{} .

编辑 2:我以为我会很聪明,并在从数据库中检索时用正确的类型预先填充一个对象( game := Game{Details: FeudDetails: {}} 在调用 db...One(&game) 之前),但我的诡计不起作用:
DEBU[Mar 31 22:19:09.442] Caching show                 gid=5e814448ef5b9858b7ff4e57
TRAC[Mar 31 22:19:09.442] Before database call dtype=main.FeudDetails
TRAC[Mar 31 22:19:09.446] After database call dtype=bson.M

最佳答案

忽略 Details在(非)编码期间

更改 Game 的定义所以bson不尝试对 Details 做任何事情 field :

type Game struct {
...
Details interface{} `json:"details" bson:"-"`
}

解码 Details手动
func (game *Game) SetBSON(r bson.Raw) error {
// Unmarshall everything except Details
type tempGame Game
err := r.Unmarshal((*tempGame)(game)) // this is necessary to prevent recursion
if err != nil {
return err
}
// Get the raw data for Details
var d struct {
Details bson.Raw
}
if err := r.Unmarshal(&d); err != nil {
return err
}
gameType, ok := games[game.Type]
if ok {
// Use individual processing based on game Type
game.Details, err = gameType.LoadDetails(d.Details)
if err != nil {
return err
}
// fmt.Sprintf("%T", game.Details) => main.FeudDetails
}
return nil
}

编码(marshal) Details手动

据我所知,获得 bson 的唯一途径包括 Details在我们告诉它在原始结构中省略它之后,是创建一个完整的其他结构,将数据一个一个地复制,并在 GetBSON 中使用该类型。 .似乎必须有更好的方法。

关于go - 如何使用 bson.SetBSON 或 bson.Raw?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60961641/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com