
本文介绍如何在 go 语言中正确解析包含多个 yaml 文档的数据(如 yaml 列表或多个文档分隔符),避免因格式不匹配导致仅解析最后一个对象的问题,并提供可直接运行的结构化示例。
YAML 格式本身不支持在同一文档流中重复出现相同顶层键(如连续两个 first:),因此原始示例中看似“两个对象”的 YAML 实际被解析器视为单个映射(map),后出现的键值对会覆盖前一个——这正是 First 和 Second 字段最终只保留第二组数据的原因。
要批量解析多个独立 YAML 结构,推荐采用 YAML 序列(即数组) 方式组织数据:将每个逻辑对象作为列表的一项。这是最简洁、标准且与 yaml.v2 兼容性最佳的做法。
以下为修正后的完整可运行示例:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"log"
)
type Container struct {
First string `yaml:"first"`
Second struct {
Nested1 string `yaml:"nested1"`
Nested2 string `yaml:"nested2"`
Nested3 string `yaml:"nested3"`
Nested4 int `yaml:"nested4"`
} `yaml:"second"`
}
var data = `
- first: first value
second:
nested1: GET
nested2: /bin/bash
nested3: /usr/local/bin/customscript
nested4: 8080
- first: second value
second:
nested1: POST
nested2: /bin/ksh
nested3: /usr/local/bin/customscript2
nested4: 8081
`
func main() {
var containers []Container // 注意:声明为切片而非单个实例
err := yaml.Unmarshal([]byte(data), &containers)
if err != nil {
log.Fatalf("YAML 解析失败: %v", err)
}
fmt.Printf("---共解析 %d 个容器:\n", len(containers))
for i, c := range containers {
fmt.Printf("[%d] %+v\n", i+1, c)
}
}✅ 输出结果:
立即学习“go语言免费学习笔记(深入)”;
---共解析 2 个容器:
[1] {First:first value Second:{Nested1:GET Nested2:/bin/bash Nested3:/usr/local/bin/customscript Nested4:8080}}
[2] {First:second value Second:{Nested1:POST Nested2:/bin/ksh Nested3:/usr/local/bin/customscript2 Nested4:8081}}? 关键要点说明:
- 结构体字段需添加 yaml tag(如 yaml:"first"):确保字段名与 YAML 键名大小写及拼写完全匹配,否则可能静默忽略;
- 目标变量必须为切片类型 []Container:yaml.Unmarshal 会自动将 YAML 数组映射为 Go 切片;
- 不建议使用多文档分隔符 --- 解析多个独立文档:yaml.v2 默认不支持一次解析多个 --- 分隔的文档(需配合 yaml.Decoder 逐个扫描,复杂度高且易出错),而 YAML 数组方式更直观、健壮;
- 若数据源无法修改为数组格式(例如来自外部 API 的多文档流),则应改用 yaml.NewDecoder 配合循环调用 Decode(),但需确保输入是合法的多文档 YAML 流(每段以 --- 开头,可选 %YAML 1.x 指令)。
总结:处理多个 YAML 结构时,优先将数据建模为 YAML 序列(- 开头的列表),并使用切片接收,这是 Go + yaml.v2 生态中最自然、最可靠的方式。










