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}