首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用bson.SetBSON或bson.Raw?

如何使用bson.SetBSON或bson.Raw?
EN

Stack Overflow用户
提问于 2020-03-31 23:52:16
回答 1查看 613关注 0票数 1

可能相关:如何在mgo (Go)中使用接口类型作为模型?

我有一个这样的结构:

代码语言:javascript
复制
type Game struct {
    ID       bson.ObjectId
    Type     string
    Location string
    Details  interface{}
}

type FeudDetails struct {
    ...
}

type TriviaDetails struct {
    ...
}

type BingoDetails struct {
    ...
}

我希望使用Type字段GameDetails反序列化为特定类型(如FeudDetailsBingoDetails的实例)。它仍然是interface{} in Game,但是我可以这样做:

代码语言:javascript
复制
feudDetails, ok := game.Details.(FeudDetails)
if ok {
    // we know this is a Feud game, and we have the details
    feudDetails.Round++
}

医生们说“可以使用bson.Raw部分地解封送或封送值”,但它们没有提供我所能找到的任何示例。

我试过用:

代码语言:javascript
复制
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。如果我这样做:

代码语言:javascript
复制
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.”

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

编辑2:我认为我很聪明,在从数据库检索时(在调用db...One(&game)之前的game := Game{Details: FeudDetails: {}}),我会用正确的类型预先填充一个对象,但我的诡计没有奏效:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2020-04-02 21:40:11

在(Un)编组期间忽略Details

更改Game的定义,这样bson就不会尝试使用Details字段做任何事情:

代码语言:javascript
复制
type Game struct {
    ...
    Details interface{} `json:"details" bson:"-"`
}

手工解封Details

代码语言:javascript
复制
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
}

Details元帅手工

据我所知,在我们让bson在原始结构中省略它之后,让它包含Details的唯一方法是创建一个完整的其他结构,逐个复制数据,并在GetBSON中使用该类型。看来一定有更好的办法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60961641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档