将XML解码为Go中的接口类型?

huangapple go评论90阅读模式
英文:

Decode XML into interface type with Go?

问题

在Go 1.3中,将XML解码为接口类型是可能的吗?

例如,如果结构体看起来像这样(简化):

type Field interface { ... }

// DataField和ControlField满足Field接口
type DataField struct { ... } // <- 一个具体类型,带有XML标签
type ControlField struct { ... } // <- 另一个具体类型,带有XML标签


type Record struct {
    Fields []Field // <- Field是一个接口
}

...
// 我们想要解码为一个record,例如:
var record Record
decoder.DecodeElement(&record, &se)
...

据我所见,使用具体类型解码XML是可行的,例如:

type Record struct {
    ControlFields []ControlField // <- 使用具体类型可以工作
    DataFields []DataField // <- 使用具体类型可以工作
}

但是,使用接口类型会失败,尽管实现已经用正确的XML标签进行了注释。

可运行的示例,请参见http://play.golang.org/p/tPlw4Y74tt或gist

英文:

Is it possible to decode XML into an interface type with Go 1.3?

For example, if the structs look something like this (simplified):

<!-- language: lang-go -->

type Field interface { ... }

// DataField and ControlField satisfy Field interface
type DataField struct { ... } // &lt;- One concrete type, with XML tags
type ControlField struct { ... } // &lt;- Another concrete type, with XML tags


type Record struct {
    Fields []Field // &lt;- Field is an interface
}

...
// we want to decode into a record, e.g.
var record Record
decoder.DecodeElement(&amp;record, &amp;se)
...

As far as I can see, it is possible to decode XML with the concrete types, e.g.:

<!-- language: lang-go -->

type Record struct {
    ControlFields []ControlField // &lt;- Using concrete type works
    DataFields []DataField // &lt;- Using concrete type works
}

But the interface type fails, although the implementations are annotated with the correct XML tags.

For a runnable example, see http://play.golang.org/p/tPlw4Y74tt or as gist.

答案1

得分: 1

从查看encoding/xml包中的代码来看,似乎接口类型被简单地跳过了:

...

switch v := val; v.Kind() {

case reflect.Interface:
// TODO: 目前,只是简单地忽略该字段。在不久的将来,如果不为nil,我们可能会选择对其进行解组。
return p.Skip()

...

Go版本:1.3。

英文:

From looking at the code in the encoding/xml package, it seems, interface types are just skipped:

...

switch v := val; v.Kind() {

case reflect.Interface:
    // TODO: For now, simply ignore the field. In the near
    //       future we may choose to unmarshal the start
    //       element on it, if not nil.
    return p.Skip()

...

Go version: 1.3.

答案2

得分: 1

你需要使用某种具体类型来初始化接口数组中的值,否则 XML 将无法推断出你所指的类型是什么:

http://play.golang.org/p/6LVgK7rza9

			// InterfaceRecord 失败
			record := InterfaceRecord{
				Fields: []Field{&amp;DataField{}},
			}

			decoder.DecodeElement(&amp;record, &amp;se)
			output, err := xml.MarshalIndent(record, &quot;  &quot;, &quot;    &quot;)
			if err != nil {
				fmt.Printf(&quot;error: %v\n&quot;, err)
			}

			os.Stdout.Write(output)

输出结果:

  &lt;record&gt;
      &lt;d tag=&quot;&quot;&gt;&lt;/d&gt;
  &lt;/record&gt;
英文:

You need to initialize the values inside your interface arrays with some concrete type or xml will not be able to infer to which type are you referring to:

http://play.golang.org/p/6LVgK7rza9

			// InterfaceRecord fails
			record := InterfaceRecord{
				Fields: []Field{&amp;DataField{}},
			}

			decoder.DecodeElement(&amp;record, &amp;se)
			output, err := xml.MarshalIndent(record, &quot;  &quot;, &quot;    &quot;)
			if err != nil {
				fmt.Printf(&quot;error: %v\n&quot;, err)
			}

			os.Stdout.Write(output)

Output:

  &lt;record&gt;
      &lt;d tag=&quot;&quot;&gt;&lt;/d&gt;
  &lt;/record&gt;

huangapple
  • 本文由 发表于 2014年8月13日 00:11:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/25269171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定