[英]Read multiple yamls in a file
How does one parse multiple yamls in a file similar to how kubectl does it?如何解析文件中的多个 yaml 类似于 kubectl 的方式?
example.yaml例子.yaml
---
a: Easy!
b:
c: 0
d: [1, 2]
---
a: Peasy!
b:
c: 1000
d: [3, 4]
There's a difference in behavior between gopkg.in/yaml.v2 and gopkg.in/yaml.v3: gopkg.in/yaml.v2 和 gopkg.in/yaml.v3 之间的行为存在差异:
V2: https://play.golang.org/p/XScWhdPHukO V3: https://play.golang.org/p/OfFY4qH5wW2 V2: https : //play.golang.org/p/XScWhdPHukO V3: https : //play.golang.org/p/OfFY4qH5wW2
Both implementations produce an incorrect result IMHO but V3 is apparently slightly worse.两种实现都会产生不正确的结果恕我直言,但 V3 显然稍差一些。
There's a workaround.有一个解决方法。 If you slightly change code in the accepted answer, it works correctly and in the same fashion with both versions of yaml package: https://play.golang.org/p/r4ogBVcRLCb
如果您稍微更改了已接受答案中的代码,它可以在两个版本的 yaml 包中以相同的方式正常工作: https : //play.golang.org/p/r4ogBVcRLCb
Solution I found using gopkg.in/yaml.v2
:我发现使用
gopkg.in/yaml.v2
解决方案:
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"path/filepath"
"gopkg.in/yaml.v2"
)
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
filename, _ := filepath.Abs("./example.yaml")
yamlFile, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
r := bytes.NewReader(yamlFile)
dec := yaml.NewDecoder(r)
var t T
for dec.Decode(&t) == nil {
fmt.Printf("a :%v\nb :%v\n", t.A, t.B)
}
}
Current gopkg.in/yaml.v3
Deocder
produces quite correct result, you just need to pay attention on creating new structure for each document and check it was parsed correctly (with nil
check), and handle EOF
error correctly:当前
gopkg.in/yaml.v3
Deocder
产生了相当正确的结果,您只需要注意为每个文档创建新结构并检查它是否被正确解析(使用nil
检查),并正确处理EOF
错误:
package main
import "fmt"
import "gopkg.in/yaml.v3"
import "os"
import "errors"
import "io"
type Spec struct {
Name string `yaml:"name"`
}
func main() {
f, err := os.Open("spec.yaml")
if err != nil {
panic(err)
}
d := yaml.NewDecoder(f)
for {
// create new spec here
spec := new(Spec)
// pass a reference to spec reference
err := d.Decode(&spec)
// check it was parsed
if spec == nil {
continue
}
// break the loop in case of EOF
if errors.Is(err, io.EOF) {
break
}
if err != nil {
panic(err)
}
fmt.Printf("name is '%s'\n", spec.Name)
}
}
Test file spec.yaml
:测试文件
spec.yaml
:
---
name: "doc first"
---
name: "second"
---
---
name: "skip 3, now 4"
---
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.