前言大家好,我是asong。今天想和大家分享的是如何在Go语言中使用结构体标签,以及如何自定义自己的结构体标签解析。大部分初学者在看公司项目代码的时候,看到的一些结构体定义会是这样的:一个标签,这个标签有什么用?在上面的例子中,标签json:"lon,omitempty"的意思是当结构字段的值被编码为一个json对象时,每个导出的字段都成为该对象的一个??成员,这个成员的名字是lon或者lat,当该字段为空时,不导出该字段;总结就是lon和lat是改名成员的名字,omitempty用来判断成员是否导出。看到这里,可能有的朋友会好奇,你怎么知道这个怎么用的?可以随便写tag吗?接下来,我们就一点点揭秘,开车!!!什么是标签?Go语言提供了通过反射找到的结构标签,在标准库json/xml中被广泛使用,orm框架也支持结构标签。使用上面的例子是因为encoding/json支持结构标签,但是它有自己的标签规则;但它们都有一个通用规则,不能更改。具体格式如下:`key1:"value1"key2:"value2"key3:"value3"...`//使用键值对空格分隔的结构标签可以有多个键值对,键和values必须用冒号隔开,values必须用双引号括起来,多个键值对必须用空格隔开,千万不要用逗号!!!如果我们想在一个值中传递多个信息怎么办?不同库的实现是不同的。在encoding/json中,多值用逗号分隔:`json:"lon,omitempty"`在gorm中,多值用分号分隔:`gorm:"column:id;primaryKey"什么符号用于分隔它们取决于它们各自库的文档。结构标签在编译阶段与成员关联,以字符串的形式关联,在运行阶段可以通过反射读取。现在大家都知道什么是结构标签了。规则还是很规范的,但是很容易出错,因为Go语言在编译阶段并没有检查其格式是否合法的键值对,所以我们一不小心就写错了。很难被发现,但我们有govet工具进行检查。具体用法我们看一个例子:typeUserstruct{Namestring`abcdefghk`Ageuint16`123:232`}funcmain(){}然后执行govetmain.go得到执行结果:#command-line-argumentsgo_vet_tag/main。go:4:2:structfieldtag`abcdefghk`notcompatiblewithreflect.StructTag.Get:badsyntaxforstructtagpairgo_vet_tag/main.go:5:2:structfieldtag`123:232`notcompatiblewithreflect.StructTag.Get:badsyntaxforstructtagvalue结构标签对的错误语法告诉我们关键-value对语法错误,structtagvaluevalue语法的错误语法错误。所以有必要在我们的项目中引入govet作为CI检查。标签使用场景Go官方帮助整理了哪些库已经支持struct标签:https://github.com/golang/go/wiki/Well-known-struct-tags。标记文档xmlhttps://godoc.org/encoding/xmljsonhttps://godoc.org/encoding/jsonasn1https://godoc.org/encoding/asn1改革https://godoc.org/gopkg.in/reform.v1dynamodbhttps://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#Marshalbigqueryhttps://godoc.org/cloud.google.com/go/bigquery数据存储https://godoc.org/cloud.google.com/go/datastorespannerhttps://godoc.org/cloud.google.com/go/spannerbsonhttps://godoc.org/labix.org/v2/mgo/bson,https://godoc.org/go.mongodb.org/mongo-driver/bson/bsoncodecgormhttps://godoc.org/github.com/jinzhu/gormyamlhttps://godoc.org/gopkg.in/yaml.v2tomlhttps://godoc.org/github.com/pelletier/go-toml验证https://github.com/go-playground/validatormapstructurehttps://godoc.org/github.com/mitchellh/mapstructure解析器https://godoc.org/github.com/alecthomas/participleprotobufhttps://godoc.org/github.com/mitchellh/mapstructure解析器github.com/golang/protobufdbhttps://github.com/jmoiron/sqlxurlhttps://github.com/google/go-querystring特征https://github.com/nikolaydubina/go-featureprocessinglikejson,yaml,gorm,validate,mapstructure,protobuf的结构标签是很常用的。gin框架集成了validate库进行参数校验,方便很多。我写了一篇关于v的文章Alidate的文章:老大:这小子到现在还不会用validator库做数据校验。打开后~~~可以关注一下这些库是怎么使用的。可以看看官方文档介绍,很详细。特定场景下使用!!!自定义结构标签现在我们可以回答开头的问题了。结构标签可以随意写,只要符合语法规则即可,但有些库不支持这种标签。在的情况下,随机写入的标签是没有意义的。如果我们想让我们的标签变得有意义,我们需要提供一种解析方法。标签可以通过反射获取,那么我们来看一个例子,看看如何使用反射获取自定义结构标签。typeUserstruct{Namestring`asong:"Username"`Ageuint16`asong:"age"`Passwordstring`asong:"min=6,max=10"`}funcgetTag(uUser){t:=reflect.TypeOf(u)fori:=0;i
