Go-YAML Field Names

I wasted away a good thirty minutes trying to figure out why I couldn’t parse my YAML config file this morning using go-yaml.

package main

import (
    "fmt"
    "log"
    "gopkg.in/yaml.v2"
)

var configText = `
  Message: Welcome
  UpdateInterval: 5
  EmailAddresses:
    - john.doe@example.com
    - jane.doe@example.com`

type Config struct {
    Message        string
    UpdateInterval int
    EmailAddresses []string
}

func main() {
    var c Config
    if err := yaml.Unmarshal([]byte(configText), &c); err != nil {
        log.Fatalf("Failed to parse yaml: %v", err)
    }

    fmt.Printf("Config: %+v\n", c)
}

Output:

Config: {Message: UpdateInterval:0 EmailAddresses:[]}

As you can see in the output, no errors occur but the struct fields are not initialized properly. Message should be Welcome, UpdateInterval should be 5, and there should be two email addresses.

It turns out that go-yaml expects the YAML field corresponding to a struct field to be lowercase. So if your struct field is UpdateInterval, the corresponding field in YAML is updateinterval. When I changed my config, I got the output I was expecting:

var configText = `
  message: Welcome
  updateinterval: 5
  emailaddresses:
    - john.doe@example.com
    - jane.doe@example.com`

Output:

Config: {Message:Welcome UpdateInterval:5 EmailAddresses:[john.doe@example.com jane.doe@example.com]}

I didn’t really like the all-lowercase field names in my config, so I used struct field tags to tell go-yaml what the corresponding YAML field names will look like and reverted to my original config:

var configText = `
  Message: Welcome
  UpdateInterval: 5
  EmailAddresses:
    - john.doe@example.com
    - jane.doe@example.com`

type Config struct {
    Message        string   `yaml:"Message"`
    UpdateInterval int      `yaml:"UpdateInterval"`
    EmailAddresses []string `yaml:"EmailAddresses"`
}

Output:

Config: {Message:Welcome UpdateInterval:5 EmailAddresses:[john.doe@example.com jane.doe@example.com]}

Hopefully this will save someone else some time, because this drove me crazy this morning.