直接与间接嵌套的结构

Red*_*ick 6 xml struct nested go

xml:Unmarshal的Go 文档中,有一个解组此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>
Run Code Online (Sandbox Code Playgroud)

使用这些结构

    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
    }
Run Code Online (Sandbox Code Playgroud)

注意,Result包含对单独定义的引用Address.显然,这段代码有效.


当我试图解组这个xml

<C>
  <D>
    <E>Fred</E>
    <F>42</F>
  </D>
</C>
Run Code Online (Sandbox Code Playgroud)

使用这些结构

type D struct { 
  E string
  F int
}
type C struct {   // Compiles OK but result empty.
  D 
} 
Run Code Online (Sandbox Code Playgroud)

我得到空洞的结果{{ 0}}.然而,下面的结构可以正常生成{{Fred 42}}

type C struct {   // This works.
  D struct { 
    E string
    F int
  }
}
Run Code Online (Sandbox Code Playgroud)

请参阅游乐场示例.

我错过了一些关于结构的微妙观点吗?

icz*_*cza 6

当你这样做:

type C struct {
    D
}
Run Code Online (Sandbox Code Playgroud)

这称为嵌入(D匿名字段或嵌入字段).您可能会认为这就好像嵌入类型的字段(和方法)成为嵌入器类型的一部分(它们被提升).所以在这种情况下,写作C.E和"合法" C.F.

当你这样做时:

type C struct {
    D struct {
      E string
      F int
    }
}
Run Code Online (Sandbox Code Playgroud)

不是嵌入(或"嵌套").这D是一个"常规",该类型的命名字段C.D是字段的名称,后跟一个匿名类型文字,即字段的类型.在这里写作C.E也不合法C.F,只有C.D.EC.D.F.这是您尝试解组的XML结构的正确映射,因此这是有效的(在Go Playground上尝试).

请注意,如果您将嵌入更改为常规字段,它也可以工作(在Go Playground上尝试):

type C struct {
    D D
}
Run Code Online (Sandbox Code Playgroud)

另请注意,D如果在字段标记中指定XML元素路径,则可以跳过整个包装器结构:

type C struct {
    E string `xml:"D>E"`
    F int    `xml:"D>F"`
}
Run Code Online (Sandbox Code Playgroud)

Go Playground尝试一下.