0

I have a dilemma to store some data in an unstructured field. Let's say I have these to store:

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
}

Let's say I choose json as a serializer (I will probably go for msgpack, but that's another story).

Which way do you think is the most appropriate:

Solution 1

one container that contains all the message types, and simply use the default marshal/unmarshal:

package main

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

And then, I just need to check which of the field is nil to know what to do with it.

Solution 2

A more "typed" solution, with interfaces and 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
}

I benchmarked both, they have around the same processing time and same mem usage, but I'm wondering which of them could be more idiomatic?

VsM
  • 710
  • 1
  • 10
  • 23

0 Answers0