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.