YAML
suggest changeYAML is a popular format for serializing data in a human friendly format. Think JSON but easier to read.
Thanks to its expressivness and readability, YAML is popular as a format for configuration files.
It’s also used in more complex scenarios like driving Ansible server automation.
There is no package in standard library for hanlding YAML format but there are community libraries including gopkg.in/yaml.v2.
Reading YAML file into a Go struct
dependencies:
- name: apache
version: 1.2.3
repository: http://example.com/charts
- name: mysql
version: 3.2.1
repository: http://another.example.com/charts
// Dependency describes a dependency
type Dependency struct {
Name string
Version string
RepositoryURL string `yaml:"repository"`
}
type YAMLFile struct {
Dependencies []Dependency `yaml:"dependencies"`
}
f, err := os.Open("data.yml")
if err != nil {
log.Fatalf("os.Open() failed with '%s'\n", err)
}
defer f.Close()
dec := yaml.NewDecoder(f)
var yamlFile YAMLFile
err = dec.Decode(&yamlFile)
if err != nil {
log.Fatalf("dec.Decode() failed with '%s'\n", err)
}
fmt.Printf("Decoded YAML dependencies: %#v\n", yamlFile.Dependencies)
YAML decoding is very similar to JSON decoding.
If you know the structure of YAML file, you can define structs that mirror this structure and pass a pointer to a struct describing top-level structure to yaml.Decoder.Decode()
function (or yaml.Unmarshal()
if decoding from []byte
slice).
YAML decoder does intelligent mapping between struct field names and names in YAML file so that e.g. name
value in YAML is decoded into field Name
in a struct.
It’s best to create explicit mappings using yaml
struct tags. I only omitted them from the example to illustrate the behavior when they are not specified.
Writing Go struct to YAML file
type Person struct {
fullName string
Name string
Age int `yaml:"age"`
City string `yaml:"city"`
}
p := Person{
Name: "John",
Age: 37,
City: "SF",
}
d, err := yaml.Marshal(&p)
if err != nil {
log.Fatalf("yaml.Marshal failed with '%s'\n", err)
}
fmt.Printf("Person in YAML:\n%s\n", string(d))
yaml.Marshal
takes interface{} as an argument. You can pass any Go value, it’ll be wrapped into interface{} with their type.
Marshaller will use reflection to inspect passed value and encode it as YAML strings.
When serializing structs, only exported fields (whose names start with capital letter) are serialized / deserialized.
In our example, fullName is not serialized.
Structs are serialized as YAML dictionaries. By default dictionary keys are the same as struct field names.
Struct field Name is serialized under dictionary key Name.
We can provide custom mappings with struct tags.
We can attach arbitrary struct tags string to struct fields.
yaml:"age"
instructs YAML encoder / decoder to use name age
for dictionary key representing field Age
.
When serializing structs, passing the value and a pointer to it generates the same result.
Passing a pointer is more efficient because passing by value creates unnecessary copy.