原文链接:Go语言中构造体打Tag是什么意思?

前言

asongGo

大多数初学者在看公司的我的项目代码时,看到的一些构造体定义会是这样的:

type Location struct {
    Longitude float32 `json:"lon,omitempty"`
    Latitude  float32 `json:"lat,omitempty"`
}

字段前面会有一个标签,这个标签有什么用呢?

json:"lon,omitempty"jsonlonlatlonlatomitempty

看到这里,有一些敌人可能会好奇,这个你是怎么晓得这样应用的呢?我能够轻易写标签吗?

接下来咱们就一点点来揭秘,开车!!!

什么是标签

Gojson/xmlormencoding/json
`key1:"value1" key2:"value2" key3:"value3"...`  // 键值对用空格分隔

构造体标签能够有多个键值对,键与值要用冒号分隔,值要应用双引号括起来,多个键值对之间要应用一个空格分隔,千万不要应用逗号!!!

encoding/json
`json:"lon,omitempty"`
gorm
`gorm:"column:id;primaryKey"

具体应用什么符号分隔须要大家要看各自库的文档获取。

构造体标签是在编译阶段就和成员进行关联的,以字符串的模式进行关联,在运行阶段能够通过反射读取进去。

go vet
type User struct {
    Name string `abc def ghk`
    Age uint16 `123: 232`
}
func main()  {
}
go vet main.go
# command-line-arguments
go_vet_tag/main.go:4:2: struct field tag `abc def ghk` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair
go_vet_tag/main.go:5:2: struct field tag `123: 232` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
bad syntax for struct tag pairbad syntax for struct tag value
go vetCI

标签应用场景

Gostruct tag
Tag Documentation
xml https://godoc.org/encoding/xml
json https://godoc.org/encoding/json
asn1 https://godoc.org/encoding/asn1
reform https://godoc.org/gopkg.in/re…
dynamodb https://docs.aws.amazon.com/s…
bigquery https://godoc.org/cloud.googl…
datastore https://godoc.org/cloud.googl…
spanner https://godoc.org/cloud.googl…
bson https://godoc.org/labix.org/v…, https://godoc.org/go.mongodb….
gorm https://godoc.org/github.com/…
yaml https://godoc.org/gopkg.in/ya…
toml https://godoc.org/github.com/…
validate https://github.com/go-playgro…
mapstructure https://godoc.org/github.com/…
parser https://godoc.org/github.com/…
protobuf https://github.com/golang/pro…
db https://github.com/jmoiron/sqlx
url https://github.com/google/go-…
feature https://github.com/nikolaydub…
jsonyamlgormvalidatemapstructureprotobufginvalidatevalidate

具体这些库中是怎么应用的,大家能够看官网文档介绍,写的都很具体,具体场景具体应用哈!!!

自定义构造体标签

当初咱们能够答复结尾的一个问题了,构造体标签是能够随便写的,只有合乎语法规定,任意写都能够的,然而一些库没有反对该标签的状况下,随便写的标签是没有任何意义的,如果想要咱们的标签变得有意义,就须要咱们提供解析办法。能够通过反射的形式获取标签,所以咱们就来看一个例子,如何应用反射获取到自定义的构造体标签。

type User struct {
    Name string `asong:"Username"`
    Age  uint16 `asong:"age"`
    Password string `asong:"min=6,max=10"`
}
func getTag(u User) {
    t := reflect.TypeOf(u)

    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        tag := field.Tag.Get("asong")
        fmt.Println("get tag is ", tag)
    }
}

func main()  {
    u := User{
        Name: "asong",
        Age: 5,
        Password: "123456",
    }
    getTag(u)
}

运行后果如下:

get tag is  Username
get tag is  age
get tag is  min=6,max=10
TypeOfStructFieldTag
// A StructField describes a single field in a struct.
type StructField struct {
    Name string
    PkgPath string
    Type      Type      // field type
    Tag       StructTag // field tag string
    Offset    uintptr   // offset within struct, in bytes
    Index     []int     // index sequence for Type.FieldByIndex
    Anonymous bool      // is an embedded field
}
TagGetLoopup
func (tag StructTag) Get(key string) string
func (tag StructTag) Lookup(key string) (value string, ok bool)
GetLookupLookupkeyGet

总结

Govalidaetag
github
asong

欢送关注公众号:Golang梦工厂