【问题标题】:Read multiple yamls in a file读取文件中的多个 yaml
【发布时间】: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]

【问题讨论】:

    标签: go yaml


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      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

      【讨论】:

        【解决方案3】:

        当前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"
        ---
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-05
          • 2019-01-09
          • 1970-01-01
          • 2015-04-22
          • 2019-01-24
          • 2015-12-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多