直接嵌套结构体 vs 间接嵌套结构体

6
在 Go 的 XML 反序列化文档 中,有一个示例可以反序列化此 XML。
    <Person>
        <FullName>Grace R. Emlin</FullName>
        <Company>Example Inc.</Company>
        <Email where="home">
            <Addr>gre@example.com</Addr>
        </Email>
        <Email where='work'>
            <Addr>gre@work.com</Addr>
        </Email>
        <Group>
            <Value>Friends</Value>
            <Value>Squash</Value>
        </Group>
        <City>Hanga Roa</City>
        <State>Easter Island</State>
    </Person>

使用这些结构体
    type Address struct {
        City, State string
    }
    type Result struct {
        XMLName xml.Name `xml:"Person"`
        Name    string   `xml:"FullName"`
        Phone   string
        Email   []Email
        Groups  []string `xml:"Group>Value"`
        Address
    }

请注意,Result 包含对单独定义的 Address 的引用。显然,这段代码运行正常。
当我尝试对这个XML进行取消编组时
<C>
  <D>
    <E>Fred</E>
    <F>42</F>
  </D>
</C>

使用这些结构体
type D struct { 
  E string
  F int
}
type C struct {   // Compiles OK but result empty.
  D 
} 

我得到了空的结果{{ 0 }}。然而下面的结构正常工作,产生{{ Fred 42 }}
type C struct {   // This works.
  D struct { 
    E string
    F int
  }
}

请查看游乐场示例

我是否忽略了关于结构体的一些微妙之处?

1个回答

6
当你这样做时:
type C struct {
    D
}

这被称为嵌入D是一个匿名字段或嵌入字段)。你可以将其视为嵌入类型的字段(和方法)成为嵌入器类型的一部分(它们被提升)。因此,在这种情况下,编写C.EC.F是“合法的”。
当您执行以下操作时:
type C struct {
    D struct {
      E string
      F int
    }
}

这不是嵌套。这里的DC类型的一个"常规"、命名字段。 D是字段的名称,后面跟着一个匿名类型文字,表示字段的类型。在这里,不能写C.EC.F,只能写C.D.EC.D.F。这是您尝试取消编组的XML结构的正确映射,因此它可以工作(请在Go Playground上尝试)。请注意,如果将嵌入更改为常规字段,则它也可以工作(请在Go Playground上尝试)。
type C struct {
    D D
}

请注意,如果您在字段标记中指定XML元素路径,则可以跳过整个D包装结构:
type C struct {
    E string `xml:"D>E"`
    F int    `xml:"D>F"`
}

Go Playground上尝试一下。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接