Возможно связано: Как использовать тип интерфейса в качестве модели в м go (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
в специфицированный c тип (например, экземпляр FeudDetails
или BingoDetails
). Это все равно будет interface{}
в Game
, но тогда я смогу сделать это:
feudDetails, ok := game.Details.(FeudDetails)
if ok {
// we know this is a Feud game, and we have the details
feudDetails.Round++
}
В документах говорится, что "возможно частично или маршалировать значения" используя 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)
, но преобразование не удалось. Я думаю, я не могу сделать это таким образом, потому что базовый тип после десериализации - не a 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