---
title: "Write a struct to a YAML file in Go"
url: https://recursiveai.org/oneyaml/go/cookbook/write-yaml/
description: "Write a Go struct to a YAML file with oneyaml.Marshal: yaml tags, omitempty, nested maps and lists, and the file read back. A complete main.go with its real output."
version: "1.0.0"
---

# Write a struct to a YAML file in Go

Call `oneyaml.Marshal` on the struct and write the bytes. Fields come out in declaration order, in block style, named by their `yaml` tags.

```shell
mkdir write-yaml && cd write-yaml
go mod init example.com/write-yaml
go get oneyaml.dev/go@v1.0.0
```

Put this in `main.go` and run `go run .`:

```go
package main

import (
	"fmt"
	"log"
	"os"
	"reflect"

	oneyaml "oneyaml.dev/go"
)

type Service struct {
	Name     string            `yaml:"name"`
	Image    string            `yaml:"image"`
	Replicas int               `yaml:"replicas"`
	Ports    []int             `yaml:"ports"`
	Env      map[string]string `yaml:"env"`
	Command  []string          `yaml:"command,omitempty"`
	Note     string            `yaml:"note"`
}

func main() {
	svc := Service{
		Name:     "web",
		Image:    "nginx:1.27",
		Replicas: 2,
		Ports:    []int{80, 443},
		Env:      map[string]string{"LOG_LEVEL": "info", "PORT": "8080"},
		Note:     "no",
	}

	out, err := oneyaml.Marshal(svc)
	if err != nil {
		log.Fatal(err)
	}
	if err := os.WriteFile("service.yaml", out, 0o644); err != nil {
		log.Fatal(err)
	}
	fmt.Print(string(out))

	// Read it back: the same value.
	var back Service
	if err := oneyaml.Unmarshal(out, &back); err != nil {
		log.Fatal(err)
	}
	fmt.Println("round trip equal:", reflect.DeepEqual(back, svc))
}
```

```text
name: web
image: nginx:1.27
replicas: 2
ports:
  - 80
  - 443
env:
  LOG_LEVEL: info
  PORT: '8080'
note: 'no'
round trip equal: true
```

`command` is empty and `omitempty` leaves it out. Map keys come out sorted. Strings that some reader could take for another type are quoted, so the file means what the struct held for every parser: `'8080'`, and `'no'`, which unquoted a YAML 1.1 parser such as yaml.v2 would read as `false`. To stream several documents to a writer, use `oneyaml.NewEncoder(w)`.

## Limits

- **No comments.** A struct has nowhere to keep them. To change a file people maintain by hand and keep its comments, edit it as a `Document`: [edit YAML and keep its comments](https://recursiveai.org/oneyaml/go/cookbook/edit-yaml-keep-comments/).
- **Map keys are sorted.** When the order matters, use a struct, whose fields keep their declaration order.

To read the file into the struct: [parse YAML into a struct](https://recursiveai.org/oneyaml/go/cookbook/parse-yaml-into-structs/).
