My blog post from yesterday made me think… how can you marshal and unmarshal enums in Go correctly?
So I modified internal/coffee/coffee.go
and added a MarshalText()
and UnmarshalText()
methods:
package coffee
import (
"fmt"
"strings"
)
//go:generate stringer -linecomment -type=Coffee
type Coffee int
const (
Drip Coffee = iota // drip coffee
Latte // latte
Breve // breve
Cappuccino // cappuccino
)
func (c Coffee) MarshalText() ([]byte, error) {
return []byte(c.String()), nil
}
func (c *Coffee) UnmarshalText(text []byte) error {
want := string(text)
for i := 0; i < len(_Coffee_index)-1; i++ {
name := _Coffee_name[_Coffee_index[i]:_Coffee_index[i+1]]
if strings.EqualFold(name, want) {
*c = Coffee(i)
return nil
}
}
return fmt.Errorf("invalid Coffee %q", want)
}
I then modified main.go
to add a new type named Drink
which expected a Coffee
in its field:
package main
import (
"encoding/json"
"fmt"
"goenumtest/internal/coffee"
)
type Drink struct {
Type coffee.Coffee `json:"type"`
}
func PrintCoffee(c coffee.Coffee) {
fmt.Println("Coffee type is:", c)
}
func main() {
PrintCoffee(coffee.Drip)
PrintCoffee(coffee.Latte)
payload := []byte(`{"type":"cappuccino"}`)
drink := Drink{}
if err := json.Unmarshal(payload, &drink); err != nil {
panic(err)
}
fmt.Println("Unmarshaled drink is:", drink)
s, err := json.Marshal(drink)
if err != nil {
panic(err)
}
fmt.Println("Marshaled drink is:", string(s))
}
This worked great!
Running main.go
shows:
$ go run main.go
Coffee type is: drip coffee
Coffee type is: latte
Unmarshaled drink is: {cappuccino}
Marshaled drink is: {"type":"cappuccino"}
I’ve updated my repo with this new code.