英文:
Reading multiple documents from a YAML file and marshaling them with go yaml v3
问题
我正在尝试使用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?
英文:
I'm trying to use gopkg.in/yaml.v3
to read a file containing
multiple YAML documents, and then marshal each individual document
back into YAML. My sample input looks like:
name: doc1
---
name: doc2
---
name: doc3
I'm able to unmarshal the file just fine, but I run into unexpected
errors when trying to marshal the individual documents. My code looks
like:
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)
}
}
Running this code with the sample input results in:
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
The code seems to be parsing the document correctly; if I replace it
with:
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")
}
}
I end up with what I expect:
Found a doc
Found a doc
Found a doc
The problem only crops up when marshaling. Am I correctly using the v3 api?
答案1
得分: 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文档。生成的文档的结构将反映值本身的结构。接受映射和指针(指向结构、字符串、整数等)作为输入值。
来源:https://pkg.go.dev/gopkg.in/yaml.v2#Marshal
由于你尝试对yaml.Node
进行序列化,而它是一个结构体,所以你必须传递结构体的指针而不是值本身,正如文档所述。
英文:
There was a small mistake in your code.
It should be content, err := yaml.Marshal(&node)
. You missed the &
.
This works,
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)
}
}
The docs for yaml.Marshal
says,
> Marshal serializes the value provided into a YAML document. The structure of the generated document will reflect the structure of the value itself. Maps and pointers (to struct, string, int, etc) are accepted as the in value.
Source: https://pkg.go.dev/gopkg.in/yaml.v2#Marshal
Since you are trying to marshal yaml.Node
which is a struct, you must pass the pointer to the struct and not the value itself, as the docs say.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论