golang的yaml解析(使用“---”分隔的多文档解析)

yaml库

import "gopkg.in/yaml.v2"

该库可以很方便的操作yaml文件,这里先展示一下常用的解析方法:

假设有如下a.yml文件:

a: 10
b: 
	- 1
	- 2
	- 3

这个yaml很简单,里面包含了一个int型的变量a,和一个int型的数组变量b。那么与之对应的结构体也很好构造:

type YmlObj struct {
	A int
	B []int
}

使用yaml包来解析也很简单,这里我就用go的单元测试来写这个方法了:

func TestGetYamlByUnmarshal(t *testing.T) {
	y := YmlObj{}
	content, err := ioutil.ReadFile("a.yml")
	if err != nil{
		t.Error(err)
	}
	if err = yaml.Unmarshal(content, &y);err != nil{
		t.Error(err)
	}
	fmt.Println(y)
}

/*
OUTPUT:
{10 [1 2 3]}
*/

多文档

这里说的多文档,并不是指多个yaml文件,这很简单和上面没什么区别。
在yaml中,严格的讲,每个yaml文件都应该以---开头,注意,这是三个短横线。因此如果在一个yaml文件中包含多个---,那么就相当于多个yml文档,例如b.yml:

---
a: 10
b: 
	- 1
	- 2
	- 3
---
a: 20
b: 
	- 4
	- 5

这种情况在k8s中非常常见,我之前自己处理的时候想法也很简单,将文件读取为字符串,然后用strings.split(str, "---")来把这个文件分割为多个文档,然后在逐一解析。

可是这样是有问题的,前几天我遇到一份yml文档中包含多个连续的短横线,那结果也可以预见:yml文档被分割成了多个不完整的部分,解析自然也会失败。

实际上yaml这个包对于这种情况是有官方的解决方案的:decode
下面上代码:

func TestGetYaml(t *testing.T) {
	file, err := os.Open("b.yaml")
	if err != nil{
		t.Error(err)
	}
	dec := yaml.NewDecoder(file)
	y := YmlObj{}
	err := dec.Decode(&y)
	for err == nil{
		fmt.Println(y)
		err = dec.Decode(&y)
	}
	if !errors.Is(err, io.EOF){
		t.Error(err)
	}
	fmt.Println("Parse yaml complete!")
}
/*
OUTPUT:
{10 [1 2 3]}
{20 [4 5]}
*/

可以看出来,yaml.NewDecoder返回的decoder在调用Decode方法的时候,每次都会从该文件中取出一个yaml文档进行解析,该文件中的所有文档都读取完成后,就会返回一个io.EOFerror,如果判断是该error,就代表以及解析完毕。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您只需要解析 YAML 文件中的一部分,并修改其中的某些值,可以使用 Go 语言中的 yaml 包和 map[string]interface{} 类型。 以下是一个示例代码片段,假设我们要修改以下 YAML 文件的 "name" 字段: ```yaml person: info: name: John age: 30 ``` ```go package main import ( "fmt" "io/ioutil" "gopkg.in/yaml.v2" ) func main() { // 读取 YAML 文件 data, err := ioutil.ReadFile("person.yaml") if err != nil { panic(err) } // 解析 YAML 文件中的 person.info 字段为一个 map[string]interface{} 类型 var person map[string]interface{} err = yaml.Unmarshal(data, &person) if err != nil { panic(err) } // 修改 person 字段中的 info.name 值 person["info"].(map[interface{}]interface{})["name"] = "Alice" // 将修改后的数据写回到 YAML 文件 newData, err := yaml.Marshal(&person) if err != nil { panic(err) } err = ioutil.WriteFile("person.yaml", newData, 0644) if err != nil { panic(err) } fmt.Println("person.yaml 文件已更新!") } ``` 在这个示例中,我们首先使用 ioutil.ReadFile 函数读取 YAML 文件的内容,然后使用 yaml.Unmarshal 函数将其解析为一个 map[string]interface{} 类型。接着,我们修改该 map 中的 "name" 字段的值,然后使用 yaml.Marshal 函数将其转换回 YAML 格式的数据。最后,使用 ioutil.WriteFile 函数将修改后的数据写回到原始 YAML 文件中。 请注意,使用这种方法仅仅解析需要修改的部分,而不是将整个 YAML 文件都解析出来,这样可以提高程序的效率。另外,注意 "name" 字段在 YAML 文件中是在 "info" 字段下的,需要使用类型断言来获取该子节点的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值