yaml.marshalindent 可生成带缩进的 yaml,需传入前缀和缩进字符串(如 "", " "),且结构体字段须导出并合理使用 yaml tag 控制 key 名、omitempty 等行为;时间等类型需自定义 marshalyaml 实现格式控制,map 无序性导致键顺序不可控,推荐用 struct 替代 map 保证顺序。

用 yaml.MarshalIndent 生成带缩进的 YAML 字符串
Go 标准库不支持 YAML,必须用第三方库(如 gopkg.in/yaml.v3)。直接调用 yaml.Marshal 会输出无缩进的紧凑格式,要美观排版,必须用 yaml.MarshalIndent。
它比 yaml.Marshal 多两个参数:缩进空格数、嵌套时每级额外缩进空格数。常见用法是传 2 和 2,对应 2 空格缩进风格:
data := struct{ Name string; Age int }{"Alice", 30}
yamlBytes, err := yaml.MarshalIndent(data, "", " ") // 注意:第二个参数是前缀,通常为空字符串
if err != nil {
log.Fatal(err)
}
fmt.Println(string(yamlBytes))
输出为:
Age: 30 Name: Alice
注意:yaml.MarshalIndent 的第二个参数是每行开头的「前缀」,不是缩进字符;第三个参数才是实际用于缩进的字符串(推荐用空格,不用 \t,否则部分解析器可能报错)。
结构体字段必须可导出且有 YAML tag
YAML 库只能序列化导出字段(首字母大写),且默认使用字段名小写形式作为 key。若想控制 key 名、忽略空值或指定别名,得加 yaml tag:
-
yaml:"name"→ 输出 key 为name -
yaml:"name,omitempty"→ 该字段为空值(零值)时不输出 -
yaml:"-"→ 完全忽略该字段 -
yaml:",omitempty,string"→ 同时启用 omitempty 和 string 转换(比如把int当字符串输出)
例如:
type User struct {
ID int `yaml:"id"`
Name string `yaml:"name,omitempty"`
Email string `yaml:"email"`
}
若 Name 为空字符串,就不会出现在 YAML 中。
时间类型和自定义类型容易被转成非预期格式
time.Time 默认序列化为 RFC3339 字符串(如 2024-05-20T14:23:11Z),看起来正常,但如果你希望用更短的 2024-05-20 格式,不能靠配置选项解决——gopkg.in/yaml.v3 不提供全局时间格式钩子。
可行做法只有两个:
- 字段类型改用
string,手动赋值格式化后的时间 - 为结构体实现
MarshalYAML()方法,接管该字段序列化逻辑
后者更干净,但要注意:一旦实现了 MarshalYAML,整个结构体都由你控制输出,不能再依赖默认行为。例如:
func (u User) MarshalYAML() (interface{}, error) {
type Alias User // 防止无限递归
return struct {
Alias
Birthday string `yaml:"birthday"`
}{
Alias: (Alias)(u),
Birthday: u.Birthday.Format("2006-01-02"),
}, nil
}
嵌套结构体与 map 混用时缩进仍生效,但顺序不可控
yaml.MarshalIndent 确保缩进正确,但 Go map 是无序的,如果结构体里嵌了 map[string]interface{} 或直接用了 map,YAML 键顺序每次运行可能不同。这不是 bug,是语言特性。
若需固定顺序(比如配置文件生成),不要用 map,改用有序结构:
- 定义明确字段的 struct(最推荐)
- 用
[]map[string]interface{}+ 手动排序 key 列表再构造 map(麻烦且易错) - 用第三方库如
github.com/kr/pretty做后处理(不推荐,破坏 YAML 语义)
另外,yaml.v3 对 nil slice 或 map 输出为 null,而非省略;若想省略,必须配合 omitempty tag,且确保字段本身是 pointer 或 interface 类型。
真正麻烦的不是怎么加缩进,而是字段可见性、tag 控制粒度、以及时间/浮点/零值等边缘情况的显式约定——这些不提前想清楚,生成的 YAML 看着整齐,却可能在下游解析时出问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











