doushi1957 2015-01-20 12:33
浏览 52
已采纳

前往:将XML Unmarshal嵌套结构插入接口{}

I come from a Python background and this is my first proper foray into Go so I don't think things are clicking quite yet.

I'm currently implementing the Affiliate Window XML API in Go. The API follows a standard structure for Requests and Responses so to that end I'm trying to keep things dry. Envelopes always have the same structure, something like this:

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

The contents Header and Body will be different depending on what I'm requesting and the response so I created a base 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"`
}

This works well for marshaling the XML for a request but I'm having problems with unmarshaling:

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?
}

This http://play.golang.org/p/v-MkfEyFPM probably describes the problem better in code than I can in words :p

Thanks,

Chris

  • 写回答

1条回答 默认 最新

  • donglunzai4288 2015-01-20 12:41
    关注

    The type of the Header field inside the Envelope struct is interface{} which is not a struct so you cannot refer to any of its fields.

    In order to refer to a field named Quota, you have to declare Header with a static type which contains a Quota field, something like this:

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

    If you don't know what type it will be or you can't commit to a single type, you can leave it as interface{}, but then you have to use either Type switches or Type assertion to convert it to a static type at runtime, the latter would look something like this:

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

    Another option would be to use reflection to access named fields of the Envelope.Header value, but try to solve it in other ways if possible. If you're interested in learning more about reflection in Go, I recommend reading The Laws of Reflection blog post first.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?