英文:
Go YAML parser failing silently
问题
我正在尝试使用gopkg.in/yaml.v2
在Go中实现简单的YAML解析。
根据文档:
>可以接受映射和指针(指向结构体、字符串、整数等)作为输出值。如果结构体内部的指针未初始化,YAML包将在必要时进行初始化,以便对提供的数据进行解组。输出参数不能为nil。
>
>解码后的值的类型应与输出中的相应值兼容。如果由于类型不匹配而无法解码一个或多个值,则解码将部分继续,直到YAML内容的末尾,并返回一个*yaml.TypeError,其中包含所有未解码的值的详细信息。
请注意这里的重要部分:“如果需要,初始化结构体内部的指针”和“如果无法解码值,则返回yaml.TypeError”。
现在看一下代码:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type YamlTypeA struct {
D string `yaml:"d"`
E string `yaml:"e"`
}
type YamlTypeB struct {
F string `yaml:"f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml:"a"`
TypeB []YamlTypeB `yaml:"b"`
}
func main() {
var yamlObj YamlTypeC
text := []byte(`
---
a:
d: foo
e: bar
b: [{f: "fails"},
{f: "completely"}]
`)
err := yaml.Unmarshal(text, &yamlObj)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("OK")
fmt.Printf("TypeA.D: %s\n", yamlObj.TypeA.D)
fmt.Printf("I have %d TypeB\n", len(yamlObj.TypeB))
}
运行结果为:
OK
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4014b3]
这似乎违反了文档中的承诺。如果我将嵌套的YamlTypeA改为立即值而不是指针,结果是输出值不会被修改,但仍然没有错误:
OK
TypeA.D:
I have 0 TypeB
这是怎么回事?它只是有问题/文档不完善吗?如何从YAML中解析嵌套的结构体值?(在这里使用映射的映射很麻烦,也不是解决方案。)
英文:
I'm trying to get simple YAML parsing in go working with gopkg.in/yaml.v2
.
From the documentation:
>Maps and pointers (to a struct, string, int, etc) are accepted as
>out values. If an internal pointer within a struct is not
> initialized, the yaml package will initialize it if necessary
> for unmarshalling the provided data. The out parameter must not be nil.
>
>The type of the decoded values should be compatible with the
> respective values in out. If one or more values cannot be decoded
> due to a type mismatches, decoding continues partially until the
> end of the YAML content, and a *yaml.TypeError is returned with
> details for all missed values.
Note the important bits here: "pointer within struct initialized if nec'y", and "yaml.TypeError returned if a value can't be decoded".
Now:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type YamlTypeA struct {
D string `yaml: "d"`
E string `yaml: "e"`
}
type YamlTypeB struct {
F string `yaml: "f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml: "a"`
TypeB []YamlTypeB `yaml: "b"`
}
func main() {
var yamlObj YamlTypeC
text := []byte(`
---
a:
d: foo
e: bar
b: [{f: "fails"},
{f: "completely"}]
`)
err := yaml.Unmarshal(text,&yamlObj)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("OK")
fmt.Printf("TypeA.D: %s\n", yamlObj.TypeA.D)
fmt.Printf("I have %d TypeB\n", len(yamlObj.TypeB))
}
yields
OK
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4014b3]
which appears to violate the promises made in the documentation jointly. If I make the nested YamlTypeA immediate instead of a pointer, the result is that the output value is not touched, still no error:
OK
TypeA.D:
I have 0 TypeB
What gives here? Is it just broken / poorly documented? How can you get nested struct values to parse out of YAML? (Using maps of maps is cumbersome and not at all a solution here.)
答案1
得分: 5
你的结构标签中有空格,所以它们被忽略了:
type YamlTypeA struct {
D string `yaml:"d"`
E string `yaml:"e"`
}
type YamlTypeB struct {
F string `yaml:"f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml:"a"`
TypeB []YamlTypeB `yaml:"b"`
}
英文:
You have spaces in your struct tags, so they're being ignored:
type YamlTypeA struct {
D string `yaml:"d"`
E string `yaml:"e"`
}
type YamlTypeB struct {
F string `yaml:"f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml:"a"`
TypeB []YamlTypeB `yaml:"b"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论