We can enhance the definition of the struct by adding Tag some meta information to the tag, and in this article we'll take a few examples to get a deeper look at Tag the usage.
Structure
Structis composed of one group field , each field containing the name (optional) and the field type
package mainimport "fmt"type T1 struct { f1 string}type T2 struct { T1 f2 int64 f3, f4 float64}func main() { t := T2{T1{"foo"}, 1, 2, 3} fmt.Println(t.f1) // foo fmt.Println(t.T1.f1) // foo fmt.Println(t.f2) // 1}
fieldT1 is an inline type field , and it does not have a field name. Fieldthe definition can be as f3 f4 Common as a field type.
Label
Sometimes a string () is appended to the field definition tag . Similar to the following
type T struct { f1 string "f one" f2 string f3 string `f three` f4, f5 int64 `f four and five`}
Whether raw string or not it interpreted string can be used as a tag . If you field define a property with two names in common, then this will be appended to the tag two names, like F4,f5.
Reflection
TagCan be read through the package at run time reflection
package mainimport ( "fmt" "reflect")type T struct { f1 string "f one" f2 string f3 string `f three` f4, f5 int64 `f four and five`}func main() { t := reflect.TypeOf(T{}) f1, _ := t.FieldByName("f1") fmt.Println(f1.Tag) // f one f4, _ := t.FieldByName("f4") fmt.Println(f4.Tag) // f four and five f5, _ := t.FieldByName("f5") fmt.Println(f5.Tag) // f four and five}
Set an empty tag and not set tag effect consistently
type T struct { f1 string `` f2 string}func main() { t := reflect.TypeOf(T{}) f1, _ := t.FieldByName("f1") fmt.Printf("%q\n", f1.Tag) // "" f2, _ := t.FieldByName("f2") fmt.Printf("%q\n", f2.Tag) // ""}
Format
TagsCan be composed of key-value pairs, through the space to split the key value- key1:"value1" key2:"value2" key3:"value3" . If the tags format is OK, we can Lookup either Get get the value of the key value pair.
LookupCallback two values-corresponding values and whether to find
type T struct { f string `one:"1" two:"2"blank:""`}func main() { t := reflect.TypeOf(T{}) f, _ := t.FieldByName("f") fmt.Println(f.Tag) // one:"1" two:"2"blank:"" v, ok := f.Tag.Lookup("one") fmt.Printf("%s, %t\n", v, ok) // 1, true v, ok = f.Tag.Lookup("blank") fmt.Printf("%s, %t\n", v, ok) // , true v, ok = f.Tag.Lookup("five") fmt.Printf("%s, %t\n", v, ok) // , false}
GetThe method simply wraps the following Lookup . But the result of the success is discarded
func (tag StructTag) Get(key string) string { v, _ := tag.Lookup(key) return v}
Transformation
Converting the value of a struct to another type can be defined by tag
type T1 struct { f int `json:"foo"` } type T2 struct { f int `json:"bar"` } t1 := T1{10} var t2 T2 t2 = T2(t1) fmt.Println(t2) // {10}
When did you use the tag?
(Un) Marshaling
Tag is probably the most common in the marshaling .
import ( "encoding/json" "fmt")func main() { type T struct { F1 int `json:"f_1"` F2 int `json:"f_2,omitempty"` F3 int `json:"f_3,omitempty"` F4 int `json:"-"` } t := T{1, 0, 2, 3} b, err := json.Marshal(t) if err != nil { panic(err) } fmt.Printf("%s\n", b) // {"f_1":1,"f_3":2}}
Orm
such as Gorm-example.
Go vet
The go compiler does not force you to use a reasonable tags . But go vet can check to tag see if you are reasonable.
package maintype T struct { f string "one two three"}func main() {}> go vet tags.gotags.go:4: struct field tag `one two three` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair