【问题标题】:Reading multiple documents from a YAML file and marshaling them with go yaml v3从 YAML 文件中读取多个文档并使用 go yaml v3 编组它们
【发布时间】:2021-05-19 15:39:51
【问题描述】:

我正在尝试使用gopkg.in/yaml.v3 来读取包含 多个 YAML 文档,然后编组每个单独的文档 回到 YAML。我的示例输入如下所示:

name: doc1
---
name: doc2
---
name: doc3

我能够很好地解组文件,但我遇到了意外 尝试编组单个文档时出错。我的代码看起来 喜欢:

package main

import (
    "errors"
    "fmt"
    "io"

    "os"

    "gopkg.in/yaml.v3"
)

func main() {
    reader := io.Reader(os.Stdin)
    dec := yaml.NewDecoder(reader)

    for {
        var node yaml.Node
        err := dec.Decode(&node)
        if errors.Is(err, io.EOF) {
            break
        }
        if err != nil {
            panic(err)
        }

        content, err := yaml.Marshal(node)
        if err != nil {
            panic(err)
        }

        fmt.Printf("Found a doc\n\n%s\n", content)
    }
}

使用示例输入运行此代码会导致:

panic: yaml: expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got document start

goroutine 1 [running]:
main.main()
        /home/lars/projects/operate-first/halberd/main.go:31 +0x451

代码似乎正确地解析文档;如果我更换它 与:

package main

import (
    "errors"
    "fmt"
    "io"

    "os"

    "gopkg.in/yaml.v3"
)

func main() {
    reader := io.Reader(os.Stdin)
    dec := yaml.NewDecoder(reader)

    for {
        var node yaml.Node
        err := dec.Decode(&node)
        if errors.Is(err, io.EOF) {
            break
        }
        if err != nil {
            panic(err)
        }

        fmt.Printf("Found a doc\n")
    }
}

我最终得到了我的期望:

Found a doc
Found a doc
Found a doc

这个问题只会在编组时出现。我是否正确使用了 v3 api?

【问题讨论】:

    标签: go yaml


    【解决方案1】:

    您的代码中有一个小错误。
    应该是content, err := yaml.Marshal(&node)。你错过了&
    这行得通,

    package main
    
    import (
        "errors"
        "fmt"
        "io"
    
        "os"
    
        "gopkg.in/yaml.v3"
    )
    
    func main() {
        reader := io.Reader(os.Stdin)
        dec := yaml.NewDecoder(reader)
    
        for {
            var node yaml.Node
            err := dec.Decode(&node)
            if errors.Is(err, io.EOF) {
                break
            }
            if err != nil {
                panic(err)
            }
    
            content, err := yaml.Marshal(&node)
            if err != nil {
                panic(err)
            }
    
            fmt.Printf("Found a doc\n\n%s\n", content)
        }
    }
    

    yaml.Marshal 的文档说,

    Marshal 将提供的值序列化到 YAML 文档中。生成文档的结构将反映值本身的结构。映射和指针(指向 struct、string、int 等)被接受为 in 值。

    来源:https://pkg.go.dev/gopkg.in/yaml.v2#Marshal

    由于您尝试编组 yaml.Node 这是一个结构,因此您必须将指针传递给结构而不是值本身,正如文档所说。

    【讨论】:

    • 谢谢,确实有效!你能解释一下为什么将指针传递给节点有效,但值本身却不行吗?如果我将yaml.Marshal(node) 替换为yaml.Marshal(node.Content),它也可以工作。
    • @larsks 我用解释更新了答案。希望对你有帮助
    猜你喜欢
    • 1970-01-01
    • 2019-01-27
    • 2014-12-08
    • 2019-04-27
    • 2019-01-09
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2013-10-19
    相关资源
    最近更新 更多