您现在的位置是:亿华云 > 数据库
Go 语言中结构体打 Tag 是什么意思?
亿华云2025-10-08 21:13:12【数据库】6人已围观
简介前言哈喽,大家好,我是asong。今天想与大家分享Go语言中结构体标签是怎么使用的,以及怎样定制自己的结构体标签解析。大多数初学者在看公司的项目代码时,看到的一些结构体定义会是这样的:typeLoca
前言
哈喽,中结大家好,构体我是什意思asong。今天想与大家分享Go语言中结构体标签是中结怎么使用的,以及怎样定制自己的构体结构体标签解析。
大多数初学者在看公司的什意思项目代码时,看到的中结一些结构体定义会是这样的:
type Location struct { Longitude float32 `json:"lon,omitempty"` Latitude float32 `json:"lat,omitempty"` }字段后面会有一个标签,这个标签有什么用呢?构体
上面的例子中,标签json:"lon,什意思omitempty"代表的意思是结构体字段的值编码为json对象时,每一个导出字段变成该对象的中结一个成员,这个成员的构体名字为lon或者lat,并且当字段是什意思空值时,不导出该字段;总结就是中结lon、lat是构体重命名成员的名字,omitempty用来决定成员是什意思否导出。b2b供应网
看到这里,有一些朋友可能会好奇,这个你是怎么知道这样使用的呢?我可以随便写标签吗?
接下来我们就一点点来揭秘,开车!!!
什么是标签
Go语言提供了可通过反射发现的的结构体标签,这些在标准库json/xml中得到了广泛的使用,orm框架也支持了结构体标签,上面那个例子的使用就是因为encoding/json支持了结构体标签,不过他有自己的标签规则;但是他们都有一个总体规则,这个规则是不能更改的,具体格式如下:
`key1:"value1" key2:"value2" key3:"value3"...` // 键值对用空格分隔结构体标签可以有多个键值对,键与值要用冒号分隔,值要使用双引号括起来,多个键值对之间要使用一个空格分隔,千万不要使用逗号!!!
如果我们想要在一个值中传递多个信息怎么办?不同库中实现的是不一样的,在encoding/json中,多值使用逗号分隔:
`json:"lon,omitempty"`在gorm中,多值使用分号分隔:
`gorm:"column:id;primaryKey"具体使用什么符号分隔需要大家要看各自库的文档获取。亿华云计算
结构体标签是在编译阶段就和成员进行关联的,以字符串的形式进行关联,在运行阶段可以通过反射读取出来。
现在大家已经知道什么是结构体标签了,规则还是很规范的,但是很容易出错,因为Go语言在编译阶段并不会对其格式做合法键值对的检查,这样我们不小心写错了,就很难被发现,不过我们有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 valuebad syntax for struct tag pair告诉我们键值对语法错误,bad syntax for struct tag value值语法错误。
所以在我们项目中引入go vet作为CI检查是很有必要的。
标签使用场景
Go官方已经帮忙整理了哪些库已经支持了struct tag:https://github.com/golang/go/wiki/Well-known-struct-tags。
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/reform.v1 dynamodb https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#Marshal bigquery https://godoc.org/cloud.google.com/go/bigquery datastore https://godoc.org/cloud.google.com/go/datastore spanner https://godoc.org/cloud.google.com/go/spanner bson https://godoc.org/labix.org/v2/mgo/bson, https://godoc.org/go.mongodb.org/mongo-driver/bson/bsoncodec gorm https://godoc.org/github.com/jinzhu/gorm yaml https://godoc.org/gopkg.in/yaml.v2 toml https://godoc.org/github.com/pelletier/go-toml validate https://github.com/go-playground/validator mapstructure https://godoc.org/github.com/mitchellh/mapstructure parser https://godoc.org/github.com/alecthomas/participle protobuf https://github.com/golang/protobuf db https://github.com/yhoiron/sqlx url https://github.com/google/go-querystring feature https://github.com/nikolaydubina/go-featureprocessing像json、yaml、gorm、validate、mapstructure、protobuf这几个库的结构体标签是很常用的香港云服务器,gin框架就集成了validate库用来做参数校验,方便了许多,之前写了一篇关于validate的文章:boss: 这小子还不会使用validator库进行数据校验,开了~~~,可以关注一下。
具体这些库中是怎么使用的,大家可以看官方文档介绍,写的都很详细,具体场景具体使用哈!!!
自定义结构体标签
现在我们可以回答开头的一个问题了,结构体标签是可以随意写的,只要符合语法规则,任意写都可以的,但是一些库没有支持该标签的情况下,随意写的标签是没有任何意义的,如果想要我们的标签变得有意义,就需要我们提供解析方法。可以通过反射的方式获取标签,所以我们就来看一个例子,如何使用反射获取到自定义的结构体标签。
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这里我们使用TypeOf方法获取的结构体类型,然后去遍历字段,每个字段StructField都有成员变量Tag:
// 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 }Tag是一个内置类型,提供了Get、Loopup两种方法来解析标签中的值并返回指定键的值:
func (tag StructTag) Get(key string) string func (tag StructTag) Lookup(key string) (value string, ok bool)Get内部也是调用的Lookup方法。区别在于Lookup会通过返回值告知给定key是否存在与标签中,Get方法完全忽略了这个判断。
总结
本文主要介绍一下Go语言中的结构体标签是什么,以及如何使用反射获取到解结构体标签,在日常开发中我们更多的是使用一些库提供好的标签,很少自己开发使用,不过大家有兴趣的话可以读一下validae的源码,看看他是如何解析结构体中的tag,也可以自己动手实现一个校验库,当作练手项目。
文中代码已上传github:https://github.com/asong2020/Golang_Dream/tree/master/code_demo/struct_tag_demo
很赞哦!(7)
上一篇: 第五步:重复第四步,直到找到正确的纪录。
下一篇: 域名和网址一样吗?域名和网址有什么区别?
相关文章
- 打开https://www.aizhan.com/输入自己想要查询的域名然后按回车键,如果做过网站都会有数据显示出来
- 数据中心应用基础设施要求有哪些
- “加速一切”,NVIDIA CEO 黄仁勋在 COMPUTEX 开幕前发表主题演讲
- 携手攀登安全“芯”高地!2024紫光同芯合作伙伴大会安全芯片创新应用论坛圆满落幕
- 四、配置网站,填充内容
- 全球芯片行业有望在艰难的2023年之后反弹
- 什么是无人数据中心?应该使用无人数据中心吗?
- 普洛斯怀来数据中心获Uptime M&O认证,以高品质服务持续提升客户体验
- 网站页面结构改版,仅是页面样式发生变化,不会对排名、收录有影响;只有涉及到页面URL改变,才会对网站排名、收录有影响。
- NVIDIA 加速澳大利亚 Pawsey 超算中心的量子计算探索工作
热门文章
站长推荐
为了避免将来给我们的个人站长带来的麻烦,在选择域名后缀时,我们的站长最好省略不稳定的后缀域名,比如n,因为我们不知道策略什么时候会改变,更不用说我们将来是否还能控制这个域名了。因此,如果站长不是企业,或者有选择的话,如果不能选择域名的cn类,最好不要选择它。
Dan 说 React 服务端组件并不需要服务器!看完我又迷茫了...
2024年对数据中心及其基础设施有何影响?
代理服务器:代理的工作原理
在数以亿计的网站中,我们应该抓住每一个可能带来宣传的机会,域名可以带有企业的名字,一般可以使用汉语拼音或者英语单词或者是相关缩写的形式,只要用户记住了你企业的名字,就能很容易的打出你的网站域名,同样的,记住了网站域名也能很快的记住你公司的名字。
如何提高传统数据中心的效率和可持续性
KADC 2025 东方通与鲲鹏深化合作 共筑RAG解决方案与出海新生态
一文带你了解量子计算的力量