01-数据类型之值类型之结构体
Tag 简介
Tag 用于标识结构体字段的额外属性,有点类似于注释。Tag 是结构体在编译阶段关联到成员的元信息字符串,在运行的时候通过反射的机制读取出来。标准库 reflect 包中提供了操作Tag的方法
结构体的字段的定义。在 reflect 包中,使用结构体 structField 表示结构体的一个字段
1 |
|
Tag 的意义
Go 的反射特性可以动态地给结构体成员赋值,正是因为有 Tag,在赋值前可以使用 Tag 来决定赋值的动作。
比如,官方的 encoding/json
包可以将一个 JSON 数据“Unmarshal”进一个结构体,此过程中就使用了 Tag。该包定义了一些 Tag 规则,只要参考该规则设置 Tag 就可以将不同的JSON数据转换成结构体。
在 Go 中,命名都是推荐用驼峰方式,并且在首字母大小写有特殊的语法含义:包外无法引用。
但是由于经常需要和其它的系统进行数据交互,例如转成json格式,存储到mongodb啊等等。这个时候如果用属性名来作为键值可能不一定会符合项目要求。
而通过 Tag,我们可以在转换成其它格式的时候,使用其中定义的字段作为键值。
1 |
|
Tag 约定
结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔,具体的格式如下:
1 |
|
Tag 本身是一个字符串,单从语义上讲,任意的字符串都是合法的。但它有一个约定的格式,那就是字符串由key:"value"
组成。
- key 必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号;
- value 以双引号标记的字符串。
注意: key 和 value 之间使用冒号分隔,冒号前后不能有空格,多个 key:"value"
之间由空格分开。
1 |
|
key 一般表示用途,比如 json
表示用于控制结构体类型与 JSON 格式数据之间的转换,protobuf 表示用于控制序列化和反序列化。value 一般表示控制指令,具体控制指令由不同的库指定。
获取 Tag 值
1 |
|
运行结果
1 |
|
一些常用的 Tag
json(JSON标签)
:由encoding/json包
使用,详细信息见json.Marshal()
xml
:由encoding/xml
包使用,详细信息见xml.Marshal()
bson(MongoDB标签)
:由gobson
使用,详细信息在bson.Marshal()
;也由mongo-go
驱动程序,在bson package doct
中有详细说明protobuf-github.com/golang/protobuf/proto
使用者,文档中有详细说明yaml
:由gopkg.in/yaml.v2
包使用,详细信息见yaml.Marshal()
db
:被github.com/jmoiron/sqlx
包使用;也被github.com/go-gorp/gorp
包使用orm(Beego标签)
:由github.com/astaxie/beego/orm
包使用,详见Models-Beego ORM
gorm(GORM标签)
:使用gorm.io/gorm
,示例可以在他们的文档中找到valid
:由github.com/asaskevich/govalidator
包使用,示例可以在项目页面中找到datastore
:由appengine/datastore
(Google App Engine平台、Datastore服务)使用,详情见属性schema
:用于github.com/gorilla/schema
填充struct HTML表单值,在包文档中有详细说明asn
:由encoding/asn1
包使用,详细信息在asn1.Marshal()
和asn1.Unmarshal()
csv
:被github.com/gocarina/gocsv
包使用env
:被github.com/caarlos0/env
包使用form(表单标签)
binding(表单验证标签)
json Tag
1 |
|
https://studygolang.com/static/pkgdoc/pkg/encoding_json.htm
json 编码
1 |
|
在 Go 语言中,如果一个结构体的字段名首字母是大写,那么它就是一个 “导出字段”(Exported Field),意味着它可以被外部的包访问和操作。反之,如果一个字段名首字母是小写,那么它就是一个 “未导出字段”(Unexported Field),只能在当前的包内部被访问和操作。
在进行 JSON 编码(encoding)或解码(decoding)时,只有结构体的导出字段才会被处理。