执行:XML 将嵌套结构解组到接口{}

Go: XML Unmarshal Nested Structs into 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

谢谢,

克里斯

Envelope 结构中 Header 字段的类型是 interface{} ,它是 而不是 一个 struct 所以你不能引用它的任何字段。

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

type HeaderStruct struct {
    Quota string
}

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

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

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 中反射的更多信息,我建议您先阅读 The Laws of Reflection 博客 post。