我在使用github.com/go-yaml/yaml
尝试使用未导出的字段解组结构时遇到了问题。结构看起来像:
type Example struct {
ExportedField string `yaml:"exported-field"`
OneMoreExported string `yaml:"one-more-exported"`
unexportedField map[string]*AnotherExample `yaml:"unexported-field"`
}
type AnotherExample struct {
Name string `yaml:"name"`
}
我想将这样的YAML解组为
exported-field: lorem ipsum
one-more-exported: dolor set
unexported-field:
something:
name: anything
我尝试的是自定义解组器:
func (example *Example) UnmarshalYAML(unmarshal func(interface{}) error) error {
type Alias Example
tmp := struct {
UnexportedField map[string]*AnotherExample `yaml:"unexported-field"`
*Alias
}{
Alias: (*Alias)(example),
}
if err := unmarshal(&tmp); err != nil {
return err
}
if tmp.UnexportedField != nil {
example.unexportedField = tmp.UnexportedField
}
example.CopyJobNonNil(Example(*tmp.Alias)) // Copies all the non-nil fields from the passed Example instance
return nil
}
调用tmp
后, unmarshal()
并不包含任何字段,但不包含其他字段 - 其他字段似乎都被省略。
Go Playground上的转载问题(虽然由于依赖性而无法正常工作):https://play.golang.org/p/XZg7tEPGXna
答案 0 :(得分:0)
因为大多数Go解组包(包括encoding/*
包)使用reflect
包来获取struct字段,而reflect
无法访问未导出的struct字段,所以unmarshaler无法解析未导出的字段。
尽管如此,仍然有办法做到这一点。您可以将YAML解组为具有公共字段的未导出类型,然后可以将其嵌入到导出类型中。同一个包中的getter和setter只能使用嵌入式结构。
例如:
// Define the types...
type innerData struct {
ExportedField string
unexportedField string
}
type Data struct {
innerData
}
// and then...
d := Data{}
DoSomeUnmarshalling(yamlbytes, &d.innerData)
// and then you can use getters/setters/whatever on `Data`
func (d *Data) GetUnexported() string {
return d.innerData.unexportedField;
}
(警告:完全未经测试)