GoLang:重构结构体中的 XML 标签定义

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

GoLang: Refactoring xml tag definition in struct

问题

在上面的示例中,我在多个结构体中重复使用了xml:"facebook"。我想知道是否可以将其提取为常量,并在所有结构体中引用它。

或者这是我必须定义结构体的方式,我已经阅读了规范/文档,但没有找到任何特定的方法来实现这一点。

这种可能吗?

PS:我的意图是减少重复的代码,因为在创建新的结构体时很容易出现输入错误(我已经遇到过几次)。

英文:
type Social struct {
	XMLName  xml.Name `xml:"social"`
	Facebook string   `xml:"facebook"`
	Twitter  string   `xml:"twitter"`
	Youtube  string   `xml:"youtube"`
}

In the above example I have the xml:"facebook" reused in multiple structs. I would like to know if I can extract it to a constant and reference it in all structs.

Or is that how you have to define the struct I read through the specs/documentations and did not find any specific way to achieve this.

Is it possible?

PS: My intention was to reduce the duplicate code as it is easy to mistype when you create a new struct (as it had happened to me few times).

答案1

得分: 2

这是要翻译的内容:

每当需要时,重复使用tag并不麻烦。请注意,规范不允许在为结构字段定义标签时使用常量或变量。结构标签只能是字符串字面量。引用自规范:结构类型:

> StructType = "struct" "{" { FieldDecl ";" } "}" .
> FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
> EmbeddedField = [ "*" ] TypeName .
> Tag = string_lit .

一种“外包”标签定义的方法是将整个结构字段“外包”到另一个结构中,并让Social嵌入该结构。

例如:

type Social struct {
	XMLName xml.Name `xml:"social"`
	HasFacebook
	Twitter string `xml:"twitter"`
	Youtube string `xml:"youtube"`
}

type HasFacebook struct {
	Facebook string `xml:"facebook"`
}

现在你可以在其他类型/结构中重复使用它:

type Social2 struct {
	HasFacebook
	Linkedin string `xml:"linkedin"`
}

测试这两种类型(SocialSocial2):

func main() {
	var s *Social
	if err := xml.Unmarshal([]byte(src), &s); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", s)

	var s2 *Social2
	if err := xml.Unmarshal([]byte(src), &s2); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", s2)
}

const src = `<social>
	<facebook>someface</facebook>
	<twitter>sometwitter</twitter>
	<linkedin>somelinkedin</linkedin>
</social>`

输出结果(在Go Playground上尝试):

&{XMLName:{Space: Local:social} HasFacebook:{Facebook:someface} Twitter:sometwitter Youtube:}
&{HasFacebook:{Facebook:someface} Linkedin:somelinkedin}
英文:

It's not a headache to repeat a tag whenever you need it. Note that the spec does not allow you to use constants or variables when defining tags for struct fields. The struct tag can only be a string literal. Quoting from Spec: Struct types:

> StructType = "struct" "{" { FieldDecl ";" } "}" .
> FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
> EmbeddedField = [ "*" ] TypeName .
> Tag = string_lit .

One way to "outsource" the tag definition would be to "outsource" the whole struct field into another struct, and have Social embed that struct.

For example:

type Social struct {
	XMLName xml.Name `xml:&quot;social&quot;`
	HasFacebook
	Twitter string `xml:&quot;twitter&quot;`
	Youtube string `xml:&quot;youtube&quot;`
}

type HasFacebook struct {
	Facebook string `xml:&quot;facebook&quot;`
}

And now you can reuse it in other types / structs:

type Social2 struct {
	HasFacebook
	Linkedin string `xml:&quot;linkedin&quot;`
}

Testing both types (Social and Social2):

func main() {
	var s *Social
	if err := xml.Unmarshal([]byte(src), &amp;s); err != nil {
		panic(err)
	}
	fmt.Printf(&quot;%+v\n&quot;, s)

	var s2 *Social2
	if err := xml.Unmarshal([]byte(src), &amp;s2); err != nil {
		panic(err)
	}
	fmt.Printf(&quot;%+v\n&quot;, s2)
}

const src = `&lt;social&gt;
	&lt;facebook&gt;someface&lt;/facebook&gt;
	&lt;twitter&gt;sometwitter&lt;/twitter&gt;
	&lt;linkedin&gt;somelinkedin&lt;/linkedin&gt;
&lt;/social&gt;`

Output (try it on the Go Playground):

&amp;{XMLName:{Space: Local:social} HasFacebook:{Facebook:someface} Twitter:sometwitter Youtube:}
&amp;{HasFacebook:{Facebook:someface} Linkedin:somelinkedin}

答案2

得分: 1

不可能。这是不可能的。

英文:

> Is it possible?

No. This is not possible.

huangapple
  • 本文由 发表于 2017年9月18日 16:56:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/46275266.html
匿名

发表评论

匿名网友

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

确定