
在 go 中使用 yaml.v2 解析含多个同类结构的 yaml 数据时,需将 yaml 组织为列表格式,并反序列化为结构体切片,而非单个结构体,从而一次性获取全部实例。
YAML 本身不支持同一层级下重复键(如连续出现两个 first:),因此原始示例中看似“两组配置”的 YAML 实际被解析器视为键冲突——后出现的值覆盖前值,最终只保留最后一组数据。这是 YAML 规范决定的行为,不是 Go 或 yaml.v2 的限制,而是数据格式问题。
✅ 正确做法是:将多组结构显式表达为 YAML 序列(即 YAML List / Array),对应 Go 中的切片([]Container):
- 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对应 Go 代码只需修改目标变量类型与解包逻辑:
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 unmarshal error: %v", err)
}
fmt.Printf("---%d container(s) found:\n", len(containers))
for i, c := range containers {
fmt.Printf("[%d] %+v\n", i+1, c)
}
}? 注意事项:
立即学习“go语言免费学习笔记(深入)”;
- 字段标签不可省略:YAML 键名默认区分大小写且不自动匹配驼峰,务必通过 `yaml:"keyname"` 显式绑定(如 First → "first");
- 嵌套结构也需标签:内层匿名结构体的字段同样需要 yaml: 标签,否则无法正确映射;
- 避免重复键陷阱:不要依赖“多个同级键”实现多实例——YAML 解析器会静默覆盖,应始终使用 - 列表语法;
- 错误处理建议:生产环境推荐配合 yaml.UnmarshalStrict(需升级至 gopkg.in/yaml.v3)防止未知字段被忽略。
? 扩展提示:若 YAML 源无法修改(如第三方固定格式),可先用正则或 yaml.Node 手动分块解析,但代价较高;优先推动 YAML 格式标准化为数组形式,更符合 Go 的类型安全与工程实践。










