我对围棋这门语言还比较陌生.

我在try 解组一条SOAP消息时遇到了问题.我的try 是抽象Body元素的内容,避免静态地定义XML struct ,因为它会根据请求的操作而变化. 不幸的是,我找不到一种方法来正确地做到这一点.在该示例中,GetContent函数应接收指向包含内容的 struct 的指针,并将其动态添加到正文中,以便进行填充.但结果并不是预期的那样.

package main

import (
    "encoding/xml"
    "fmt"
)

type Message interface{}

type EnvelopeResponse struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
    Body    Message  `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
}

type Body struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`

    Fault               *Fault  `xml:",omitempty"`
    Content             Message `xml:",omitempty"`
    SOAPBodyContentType string  `xml:"-"`
}

type Fault struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"`

    Code   string `xml:"faultcode,omitempty"`
    String string `xml:"faultstring,omitempty"`
    Actor  string `xml:"faultactor,omitempty"`
    Detail string `xml:"detail,omitempty"`
}

type GetHostNumberOfEntriesResponse struct {
    XMLName                xml.Name `xml:"urn:dslforum-org:service:Hosts:1 GetHostNumberOfEntriesResponse"`
    NewHostNumberOfEntries int64    `xml:"NewHostNumberOfEntries"`
}

func GetContent(rawXml []byte, content interface{}) {
    envelope := EnvelopeResponse{Body: Body{Content: content}}
    xml.Unmarshal(rawXml, &envelope)
}

func main() {
    b := []byte(`
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetHostNumberOfEntriesResponse xmlns:u="urn:dslforum-org:service:Hosts:1">
<NewHostNumberOfEntries>47</NewHostNumberOfEntries>
</u:GetHostNumberOfEntriesResponse>
</s:Body>
</s:Envelope>
`)
    content := &GetHostNumberOfEntriesResponse{}
    GetContent(b, content)
    fmt.Println(*content)
}

下面是操场上的例子:

https://go.dev/play/p/BBR4vEXiPbc

推荐答案

我发现的解决方案是使用泛型来表示主体的变量和参数化内容.

此代码的工作方式与我预期的一样:

package main

import (
    "encoding/xml"
    "fmt"
)

type EnvelopeResponse[T any] struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
    Body    Body[T]  `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
}

type Body[T any] struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`

    Fault               *Fault `xml:",omitempty"`
    Content             T      `xml:",omitempty"`
    SOAPBodyContentType string `xml:"-"`
}

type Fault struct {
    XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"`

    Code   string `xml:"faultcode,omitempty"`
    String string `xml:"faultstring,omitempty"`
    Actor  string `xml:"faultactor,omitempty"`
    Detail string `xml:"detail,omitempty"`
}

type GetHostNumberOfEntriesResponse struct {
    XMLName                xml.Name `xml:"urn:dslforum-org:service:Hosts:1 GetHostNumberOfEntriesResponse"`
    NewHostNumberOfEntries int64    `xml:"NewHostNumberOfEntries"`
}

func GetContent[T any](rawXml []byte, content T) {
    envelope := EnvelopeResponse[T]{Body: Body[T]{Content: content}}
    xml.Unmarshal(rawXml, &envelope)
}

func main() {
    b := []byte(`
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetHostNumberOfEntriesResponse xmlns:u="urn:dslforum-org:service:Hosts:1">
<NewHostNumberOfEntries>47</NewHostNumberOfEntries>
</u:GetHostNumberOfEntriesResponse>
</s:Body>
</s:Envelope>
`)
    content := &GetHostNumberOfEntriesResponse{}
    GetContent(b, content)
    fmt.Println(*content)
}

Go相关问答推荐

CGO如何转换为文件*类型

在Go中根据命名空间/字符串生成UUID

带有条件的for循环中缺少RETURN语句

在Mac中使用uname获取处理器体系 struct 时,在为AMD64构建Go二进制时出现错误结果

创建服务时云运行触发器执行失败

错误&对象已被Golang在K8s操作符上修改

埃拉托塞尼筛:加快交叉关闭倍数步骤

如果values.yaml文件中不存在某个属性,如何返回默认的FALSE?

理解Golang中的IOTA和常量

Go 中如何判断 struct 体是否包含另一个 struct 体?

如何将Golang测试用例的测试覆盖率值与特定阈值进行比较

Go http.FileServer 给出意外的 404 错误

确保 Go 1.20 编译时的严格可比性?

如何在 golang revel 中获取动态应用程序配置

每次有人进入我的网站时如何运行特定功能?

如何使用 Status 字段创建 Kubernetes 对象?

go 是否对 struct 使用空间填充之类的东西?

GoLang 遍历 yaml 文件

手动将 OpenTelemetry 上下文从 golang 提取到字符串中?

Go 语言的select语句