在唯一的非结构化数据存储区中序列化golang结构

时间:2019-06-10 04:12:44

标签: go marshalling

我在将一些数据存储在非结构化字段中时遇到了难题。 假设我有这些要存储:

package main

type FoodType string

const (
    BeefFood    FoodType = "beef"
    ChickenFood FoodType = "chicken"
)

type FoodI interface {
    Prepare()
    GetType() FoodType
}

type FoodContainer struct {
    FoodI
}

type Chicken struct {
    Way string
}

func (c *Chicken) Prepare() {}
func (c *Chicken) GetType() FoodType {
    return ChickenFood
}

type Beef struct {
    Way string
}

func (b *Beef) Prepare() {}
func (b *Beef) GetType() FoodType {
    return BeefFood
}

比方说,我选择json作为序列化程序(我可能会使用msgpack,但这是另一回事了。)

您认为哪种方式最合适:

解决方案1 ​​

一个包含所有消息类型的容器,只需使用默认的marshal / unmarshal:

package main

type FoodContainer struct {
    Chicken *Chicken `json:"chicken"`
    Beef    *Beef    `json:"beef"`
}

然后,我只需要检查哪个字段为零即可知道该怎么做。

解决方案2

具有接口和FoodType的更“类型化”的解决方案

package main

import (
    "encoding/json"
    "fmt"
)

type FoodContainer struct {
    FoodType
    FoodI
}

func (fc *FoodContainer) MarshalJSON() ([]byte, error) {
    return json.Marshal(&FoodContainerT{
        FoodType: fc.FoodI.GetType(),
        FoodI:    fc.FoodI,
    })
}

func (fc *FoodContainer) UnmarshalJSON(b []byte) error {
    var fct struct {
        FoodType
    }
    if err := json.Unmarshal(b, &fct); err != nil {
        return fmt.Errorf("fc UnmarshalJSON: %v", err)
    }

    switch fct.FoodType {
    case ChickenFood:
        fmt.Printf("Yeah, Chickenfood: %v\n", fct.FoodType)
        var fi struct {
            FoodI Chicken
        }
        if err := json.Unmarshal(b, &fi); err != nil {
            return fmt.Errorf("chicken UnmarshalJSON: %v", err)
        }
        fmt.Printf("%#v", fi.FoodI)
    default:
        return fmt.Errorf("no known FoodType found")
    }

    return nil
}

我对两者进行了基准测试,它们具有相同的处理时间和相同的内存使用率,但是我想知道其中哪一个更惯用?

0 个答案:

没有答案