Работа с YAML в Go (Golang) — библиотека gopkg.in/yaml.v3
YAML (YAML Ain't Markup Language) — это популярный формат сериализации данных, часто используемый для конфигурационных файлов, описания API (OpenAPI/Swagger), CI/CD пайплайнов (GitLab CI, GitHub Actions) и Docker Compose. В экосистеме Go (Golang) стандартной библиотеки для работы с YAML нет, поэтому разработчики используют мощную и стабильную стороннюю библиотеку gopkg.in/yaml.v3. В этой статье мы подробно разберём, как читать, писать и обрабатывать YAML в Go.
Установка библиотеки
Для начала работы добавьте пакет в ваш проект:
go get gopkg.in/yaml.v3
После этого импортируйте его в код:
import "gopkg.in/yaml.v3"
Основные структуры для работы с YAML
Библиотека yaml.v3 поддерживает:
- Маршалинг (Marshal) — преобразование Go-структур в YAML-строку.
- Анмаршалинг (Unmarshal) — парсинг YAML-строки в Go-структуру.
- Потоковый парсинг (Decoder/Encoder) для работы с файлами.
- Теги
yaml:"fieldname"для настройки имён полей.
Пример 1: Чтение YAML из строки
Самый простой случай — разобрать YAML-строку в структуру Go:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
type Config struct {
Server struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
} `yaml:"server"`
Database struct {
User string `yaml:"user"`
Pass string `yaml:"pass"`
} `yaml:"database"`
}
func main() {
yamlData := `
server:
port: 8080
host: "localhost"
database:
user: "admin"
pass: "secret"
`
var cfg Config
err := yaml.Unmarshal([]byte(yamlData), &cfg)
if err != nil {
panic(err)
}
fmt.Printf("Сервер: %s:%d\n", cfg.Server.Host, cfg.Server.Port)
fmt.Printf("База: %s\n", cfg.Database.User)
}
Пример 2: Запись YAML в файл
Для записи данных в YAML-файл используйте yaml.Marshal и запись в файловую систему:
package main
import (
"os"
"gopkg.in/yaml.v3"
)
type AppConfig struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Debug bool `yaml:"debug"`
}
func main() {
config := AppConfig{
Name: "MyApp",
Version: "1.0.0",
Debug: true,
}
data, err := yaml.Marshal(&config)
if err != nil {
panic(err)
}
err = os.WriteFile("config.yaml", data, 0644)
if err != nil {
panic(err)
}
println("Файл config.yaml создан")
}
Пример 3: Работа с вложенными и сложными структурами
YAML поддерживает списки, map-структуры и глубокую вложенность. Вот пример парсинга списка серверов:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
type Service struct {
Name string `yaml:"name"`
Ports []int `yaml:"ports"`
Enabled bool `yaml:"enabled"`
}
type Deployment struct {
Version string `yaml:"version"`
Services []Service `yaml:"services"`
}
func main() {
input := `
version: "2.1"
services:
- name: web
ports: [80, 443]
enabled: true
- name: api
ports: [3000]
enabled: false
`
var dep Deployment
if err := yaml.Unmarshal([]byte(input), &dep); err != nil {
panic(err)
}
for _, s := range dep.Services {
fmt.Printf("Сервис %s: порты %v, активен: %t\n", s.Name, s.Ports, s.Enabled)
}
}
Потоковое чтение и запись (Decoder/Encoder)
Для работы с большими файлами или потоками данных используйте yaml.Decoder и yaml.Encoder:
package main
import (
"bytes"
"fmt"
"gopkg.in/yaml.v3"
)
func main() {
// Пример с Encoder
var buf bytes.Buffer
encoder := yaml.NewEncoder(&buf)
encoder.SetIndent(2) // настройка отступов
data := map