dongshan1396 2017-09-18 08:56
浏览 223
已采纳

GoLang:重构struct中的xml标记定义

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).

  • 写回答

2条回答 默认 最新

  • dsndm82062 2017-09-18 09:05
    关注

    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:"social"`
        HasFacebook
        Twitter string `xml:"twitter"`
        Youtube string `xml:"youtube"`
    }
    
    type HasFacebook struct {
        Facebook string `xml:"facebook"`
    }
    

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

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

    Testing both types (Social and Social2):

    func main() {
        var s *Social
        if err := xml.Unmarshal([]byte(src), &s); err != nil {
            panic(err)
        }
        fmt.Printf("%+v
    ", s)
    
        var s2 *Social2
        if err := xml.Unmarshal([]byte(src), &s2); err != nil {
            panic(err)
        }
        fmt.Printf("%+v
    ", s2)
    }
    
    const src = `<social>
        <facebook>someface</facebook>
        <twitter>sometwitter</twitter>
        <linkedin>somelinkedin</linkedin>
    </social>`
    

    Output (try it on the Go Playground):

    &{XMLName:{Space: Local:social} HasFacebook:{Facebook:someface} Twitter:sometwitter Youtube:}
    &{HasFacebook:{Facebook:someface} Linkedin:somelinkedin}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

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