Go:XML Unmarshal嵌套结构到接口{}

时间:2015-01-20 12:33:25

标签: xml go struct interface

我来自Python背景,这是我第一次真正涉足Go,所以我认为事情还没有完全点击。

我目前正在Go中实施Affiliate Window XML API。 API遵循请求和响应的标准结构,因此为此,我试图保持干燥。信封总是具有相同的结构,如下所示:

<Envelope>
    <Header></Header>
    <Body></Body>
</Envelope>

内容HeaderBody会有所不同,具体取决于我提出的请求和回复,因此我创建了基座Envelope struct

type Envelope struct {
    XMLName xml.Name    `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
    NS1     string      `xml:"xmlns:ns1,attr"`
    XSD     string      `xml:"xmlns:xsd,attr"`
    Header  interface{} `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"`
    Body    interface{} `xml:"Body"`
}

这适用于为请求编组XML但我在解组时遇到问题:

func NewResponseEnvelope(body interface{}) *Envelope {
    envelope := NewEnvelope()
    envelope.Header = &ResponseHeader{}
    envelope.Body = body
    return envelope
}

func main() {
    responseBody := &GetMerchantListResponseBody{}
    responseEnvelope := NewResponseEnvelope(responseBody)

    b := bytes.NewBufferString(response)
    xml.NewDecoder(b).Decode(responseEnvelope)
    fmt.Println(responseEnvelope.Header.Quota) // Why can't I access this?
}

这个http://play.golang.org/p/v-MkfEyFPM可能在代码中比在单词中更好地描述了问题:p

谢谢,

克里斯

1 个答案:

答案 0 :(得分:2)

Header结构中Envelope字段的类型为interface{}struct,因此您无法引用任何它的领域。

为了引用名为Quota的字段,您必须使用包含Header字段的静态类型声明Quota,如下所示:

type HeaderStruct struct {
    Quota string
}

type Envelope struct {
    // other fields omitted
    Header HeaderStruct
}

如果您不知道它将是什么类型,或者您无法提交单一类型,则可以将其保留为interface{},但之后您必须使用{{3}或者Type switches在运行时将它转换为静态类型,后者看起来像这样:

headerStruct, ok := responseEnvelope.Header.(HeaderStruct)
// if ok is true, headerStruct is of type HeaderStruct
// else responseEnvelope.Header is not of type HeaderStruct

另一种选择是使用反射来访问Envelope.Header值的命名字段,但如果可能的话,尝试以其他方式解决它。如果您有兴趣了解有关Go中反思的更多信息,建议您先阅读Type assertion博文。