【发布时间】:2019-04-27 02:15:13
【问题描述】:
如何解析文件中的多个 yaml,类似于 kubectl 的处理方式?
example.yaml
---
a: Easy!
b:
c: 0
d: [1, 2]
---
a: Peasy!
b:
c: 1000
d: [3, 4]
【问题讨论】:
如何解析文件中的多个 yaml,类似于 kubectl 的处理方式?
example.yaml
---
a: Easy!
b:
c: 0
d: [1, 2]
---
a: Peasy!
b:
c: 1000
d: [3, 4]
【问题讨论】:
我使用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)
}
}
【讨论】:
gopkg.in/yaml.v2 和 gopkg.in/yaml.v3 之间的行为存在差异:
V2:https://play.golang.org/p/XScWhdPHukO V3:https://play.golang.org/p/OfFY4qH5wW2
恕我直言,这两种实现都会产生不正确的结果,但 V3 显然稍差一些。
有一个解决方法。如果您对接受的答案中的代码稍作更改,它可以正常工作,并且与两个版本的 yaml 包的工作方式相同:https://play.golang.org/p/r4ogBVcRLCb
【讨论】:
当前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)
}
}
测试文件spec.yaml:
---
name: "doc first"
---
name: "second"
---
---
name: "skip 3, now 4"
---
【讨论】: