You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中如何读取YAML文件内的重复print字段?

问题解答

1. 默认解析行为:重复键会被覆盖

常用的Go YAML解析库(比如gopkg.in/yaml.v3)默认处理重复顶级键时,会用最后出现的值覆盖之前的。比如你提供的示例YAML,直接用普通结构体解析的话,最终只会得到3,前面的1和2会丢失。

2. 如何获取所有重复的print字段

要保留所有重复键的对应值,有两种可行的实现方式:

方法一:用yaml.Node手动遍历解析

先把整个YAML内容解析成yaml.Node,再遍历所有顶级节点,收集所有print键对应的值:

package main

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v3"
)

func main() {
	data, err := os.ReadFile("test.yaml")
	if err != nil {
		panic(err)
	}

	var root yaml.Node
	if err := yaml.Unmarshal(data, &root); err != nil {
		panic(err)
	}

	var printValues []int
	// 遍历顶级映射的键值对(映射节点的Content是[key1, value1, key2, value2...]的结构)
	for i := 0; i < len(root.Content); i += 2 {
		keyNode := &root.Content[i]
		if keyNode.Value == "print" {
			var val int
			if err := root.Content[i+1].Decode(&val); err != nil {
				panic(err)
			}
			printValues = append(printValues, val)
		}
	}

	fmt.Println("所有print字段的值:", printValues) // 输出 [1 2 3]
}

方法二:自定义类型实现yaml.Unmarshaler接口

定义一个自定义类型,在解析逻辑里主动收集所有print键的值:

package main

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v3"
)

type PrintList struct {
	Prints []int
}

func (p *PrintList) UnmarshalYAML(value *yaml.Node) error {
	if value.Kind != yaml.MappingNode {
		return fmt.Errorf("expected mapping node")
	}

	for i := 0; i < len(value.Content); i += 2 {
		keyNode := value.Content[i]
		if keyNode.Value == "print" {
			var val int
			if err := value.Content[i+1].Decode(&val); err != nil {
				return err
			}
			p.Prints = append(p.Prints, val)
		}
	}
	return nil
}

func main() {
	data, err := os.ReadFile("test.yaml")
	if err != nil {
		panic(err)
	}

	var pl PrintList
	if err := yaml.Unmarshal(data, &pl); err != nil {
		panic(err)
	}

	fmt.Println("所有print字段的值:", pl.Prints) // 输出 [1 2 3]
}

3. 推荐的替代方案(规范YAML结构)

重复键属于YAML的非规范写法,不同解析器的处理逻辑可能存在差异,长期来看容易引发兼容性问题。更稳妥的做法是修改YAML结构,把重复的print字段改成数组形式:

prints:
  - 1
  - 2
  - 3

对应的Go结构体定义非常简洁:

type Print struct {
	Prints []int `yaml:"prints"`
}

解析代码也更简单直观:

package main

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v3"
)

type Print struct {
	Prints []int `yaml:"prints"`
}

func main() {
	data, err := os.ReadFile("test.yaml")
	if err != nil {
		panic(err)
	}

	var p Print
	if err := yaml.Unmarshal(data, &p); err != nil {
		panic(err)
	}

	fmt.Println("所有print字段的值:", p.Prints) // 输出 [1 2 3]
}

内容的提问来源于stack exchange,提问作者DFG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:05:34