Go语言 读取文件中的多个yaml

wwodge7n  于 2023-09-28  发布在  Go
关注(0)|答案(3)|浏览(133)

如何解析文件中的多个yamls,类似于kubectl的做法?

example.yaml

---
a: Easy!
b:
  c: 0
  d: [1, 2]
---
a: Peasy!
b:
  c: 1000
  d: [3, 4]
bprjcwpo

bprjcwpo1#

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

rqcrx0a6

rqcrx0a62#

当前的gopkg.in/yaml.v3Decoder生成的结果非常正确,您只需要在为每个文档创建新结构时注意并检查它是否正确解析(使用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"
---
anauzrmj

anauzrmj3#

我使用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)

    }
}

相关问题