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

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 shape_predictor_68_face_landmarks.dat
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制