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

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

GoLang: Refactoring xml tag definition in struct

问题

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

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

这种可能吗?

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

英文:
  1. type Social struct {
  2. XMLName xml.Name `xml:"social"`
  3. Facebook string `xml:"facebook"`
  4. Twitter string `xml:"twitter"`
  5. Youtube string `xml:"youtube"`
  6. }

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嵌入该结构。

例如:

  1. type Social struct {
  2. XMLName xml.Name `xml:"social"`
  3. HasFacebook
  4. Twitter string `xml:"twitter"`
  5. Youtube string `xml:"youtube"`
  6. }
  7. type HasFacebook struct {
  8. Facebook string `xml:"facebook"`
  9. }

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

  1. type Social2 struct {
  2. HasFacebook
  3. Linkedin string `xml:"linkedin"`
  4. }

测试这两种类型(SocialSocial2):

  1. func main() {
  2. var s *Social
  3. if err := xml.Unmarshal([]byte(src), &s); err != nil {
  4. panic(err)
  5. }
  6. fmt.Printf("%+v\n", s)
  7. var s2 *Social2
  8. if err := xml.Unmarshal([]byte(src), &s2); err != nil {
  9. panic(err)
  10. }
  11. fmt.Printf("%+v\n", s2)
  12. }
  13. const src = `<social>
  14. <facebook>someface</facebook>
  15. <twitter>sometwitter</twitter>
  16. <linkedin>somelinkedin</linkedin>
  17. </social>`

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

  1. &{XMLName:{Space: Local:social} HasFacebook:{Facebook:someface} Twitter:sometwitter Youtube:}
  2. &{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:

  1. type Social struct {
  2. XMLName xml.Name `xml:&quot;social&quot;`
  3. HasFacebook
  4. Twitter string `xml:&quot;twitter&quot;`
  5. Youtube string `xml:&quot;youtube&quot;`
  6. }
  7. type HasFacebook struct {
  8. Facebook string `xml:&quot;facebook&quot;`
  9. }

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

  1. type Social2 struct {
  2. HasFacebook
  3. Linkedin string `xml:&quot;linkedin&quot;`
  4. }

Testing both types (Social and Social2):

  1. func main() {
  2. var s *Social
  3. if err := xml.Unmarshal([]byte(src), &amp;s); err != nil {
  4. panic(err)
  5. }
  6. fmt.Printf(&quot;%+v\n&quot;, s)
  7. var s2 *Social2
  8. if err := xml.Unmarshal([]byte(src), &amp;s2); err != nil {
  9. panic(err)
  10. }
  11. fmt.Printf(&quot;%+v\n&quot;, s2)
  12. }
  13. const src = `&lt;social&gt;
  14. &lt;facebook&gt;someface&lt;/facebook&gt;
  15. &lt;twitter&gt;sometwitter&lt;/twitter&gt;
  16. &lt;linkedin&gt;somelinkedin&lt;/linkedin&gt;
  17. &lt;/social&gt;`

Output (try it on the Go Playground):

  1. &amp;{XMLName:{Space: Local:social} HasFacebook:{Facebook:someface} Twitter:sometwitter Youtube:}
  2. &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:

确定