一文读懂Go结构体标签

一文读懂Go结构体标签go结构体标签定义通过 reflect.Type 获取结构体成员信息 reflect.StructField 结构中的 Tag 被称为结构体标签

大家好,欢迎来到IT知识分享网。

一文读懂Go结构体标签

go

结构体标签定义

通过 reflect.Type 获取结构体成员信息 reflect.StructField 结构中的 Tag 被称为结构体标签(Struct Tag)。结构体标签是对结构体字段的额外信息标签。

Tag是结构体在编译阶段关联到成员的元信息字符串,在运行的时候通过反射的机制读取出来。

结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔,具体的格式如下:

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

key会指定反射的解析方式包含 json(JSON标签)、 orm(Beego标签)、gorm(GORM标签)、bson(MongoDB标签)、form(表单标签)、binding(表单验证标签).这些系统使用标签设定字段在处理时应该具备的特殊属性和可能发生的行为。这些信息都是静态的,无须实例化结构体,可以通过反射获取到。

json标签

JSON数组可以用于编码Go语言的数组和slice。

将Go语言中结构体slice转为JSON的过程叫编组(marshaling),编组通过json.Marshal函数完成。

如果在结构体slice编码成JSON的时候使用自定义的成员名,可以使用结构体成员Tag来实现。

示例:

type User1 struct { Name string `json:"username"` // 编码后的字段名为 username Age int `json:"userage"` // 编码后的字段名为 userage Sex string `json:"usersex"` // 编码后的字段名为 usersex } type User2 struct { Name string `json:"username"` Age int `json:"userage"` Sex string // 编码后的字段名为 Sex } type User3 struct { Name string `json:"username"` Age int `json:"-"` // 字段不进行序列化 Sex string } func main() { u1 := User1{"ares", 20, "man"} jsondata1, err := json.Marshal(u1) if err != nil { fmt.Println("格式错误") } else { fmt.Printf("User1结构体转json:%s\n", jsondata1) } u2 := User2{"ares", 20, "man"} jsondata2, err := json.Marshal(u2) if err != nil { fmt.Println("格式错误") } else { fmt.Printf("User2结构体转json:%s\n", jsondata2) } u3 := User3{"ares", 20, "man"} jsondata3, err := json.Marshal(u3) if err != nil { fmt.Println("格式错误") } else { fmt.Printf("User3结构体转json:%s\n", jsondata3) } }

输出为:

User1结构体转json:{"username":"ares","userage":20,"usersex":"man"} User2结构体转json:{"username":"ares","userage":20,"Sex":"man"} User3结构体转json:{"username":"ares","Sex":"man"}

“encoding/json”包的json.Marshal()方法作用就是把结构体转换为json,它读取了User结构体里面的标签,json键值对的键为定义的标签名,结构体的名字起了辅助作用,同时定义了字段数据类型。json.Unmarshal()可以把json字符串转换为结构体,在很多第三方包方法都会读取结构体标签。

标签选项

一文读懂Go结构体标签

标签选项

gorm标签

模型是标准的 struct,由基本数据类型以及实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成。
GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。
GORM 默认定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt,可以嵌套入自建结构体,tag名大小写不敏感,建议使用camelCase风格,多个标签定义用分号(;)分隔:

// gorm.Model 的定义 type Model struct { ID uint `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` }

建表示例:
结构体定义如下:

type AddUserAuth struct { gorm.BaseModel UUID string `gorm:"column:user_uuid;comment:用户UUID;type:varchar(100);"` // 用户UUID User string `gorm:"column:user_name;comment:用户名称;type:varchar(50);"` // 用户登录名 Cluster string `gorm:"column:cluster_name;comment:集群名称;type:varchar(50);"` // k8s集群 NameSpace string `gorm:"column:namespace;comment:命名空间;type:varchar(50);"` // 命名空间 ServiceName string ` gorm:"column:service_name;comment:应用名称;type:varchar(50);"` // 应用名称 ServiceType string `gorm:"column:service_type;comment:应用类型;type:varchar(50);"` // 应用类型 }

生成的建表语句如下:

CREATE TABLE `add_user_auths` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, `deleted_at` datetime DEFAULT NULL, `user_uuid` varchar(100) DEFAULT NULL COMMENT '用户UUID', `user_name` varchar(50) DEFAULT NULL COMMENT '用户名称', `cluster_name` varchar(50) DEFAULT NULL COMMENT '集群名称', `namespace` varchar(50) DEFAULT NULL COMMENT '命名空间', `service_name` varchar(50) DEFAULT NULL COMMENT '应用名称', `service_type` varchar(50) DEFAULT NULL COMMENT '应用类型', PRIMARY KEY (`id`), KEY `idx_add_user_auths_deleted_at` (`deleted_at`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

使用 GORM Migrator 创建表时,不会创建被忽略的字段。

如果想要保存 UNIX(毫/纳)秒时间戳,而不是 time,只需简单地将 time.Time 修改为 int 即可。

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag:

一文读懂Go结构体标签

字段标签

关联标签

GORM 允许通过标签为关联配置外键、约束、many2many 表:

一文读懂Go结构体标签

关联标签

form标签

Gin中提供了模型绑定,将表单数据和模型进行绑定,方便参数校验和使用。

模型绑定:

// 表单数据 type LoginForm struct { UserName string `form:"username"` Password string `form:"password"` Email string `form:"email"` } // model 或 service 层Model type Email struct { Email string Password string } func EmailLogin (c *gin.Context) { var email LoginForm if err := c.ShouldBind(&email); err != nil { ... } // 获取表单数据局 args := Email { Email: email.Email, Password: email.Password, } // 对参数进行后续使用 ...

通过 form:”email” 对表单email数据进行绑定。然后通过Bind()、ShouldBind()等方法获取参数值。

binding标签

Gin 主要提供了两组绑定方法 Must bind 与 Should bind 。gin/binding 内置模型绑定实现,将请求数据提取到合适的绑定器。

Must bind:验证不通过,就会被终止或抛出特定的错误页面

Should bind:存在绑定错误,这个错误会被返回,需要自行处理相应的请求和错误。

Gin 框架本身已经实现了多种绑定,通常用来绑定来自请求数据,有不同的结构体实例与之对应。其实现的绑定有 JSON, XML, Form,Query,FormPost,FormMultipart,ProtoBuf,MsgPack,YAML,Uri。

Gin对于数据的校验使用的是 validator.v10 包,该包提供多种数据校验方法,通过binding:””标签来进行数据校验。

校验规则见github:https://github.com/go-playground/validator/blob/master/README.md

示例:

type LoginForm struct { Email string `form:"email" binding:"email"` UserName string `form:"username" binding:"username"` Password string `form:"password" binging:"required,min=6,max=10"` }

特殊符号:

一文读懂Go结构体标签

特殊符号

必须校验

一文读懂Go结构体标签

必须校验

字符串校验

一文读懂Go结构体标签

字符串校验

范围校验

范围验证: 切片、数组和map、字符串,验证其长度;数值,验证大小范围。

一文读懂Go结构体标签

范围校验

字段校验

一文读懂Go结构体标签

字段校验

示例:

// 不同结构体校验 type S1 struct { F1 string `validate:eqcsfield=S2.F2` S2 struct { F2 string } } // 同一结构体字段相同校验 type Email struct { Email string `validate:"lte=4"` Pwd string `validate:"min=10"` Pwd2 string `validate:"eqfield=Pwd"` } // 同一结构体字段不相等 type User struct { Name string `validate:"lte=4"` Age int `validate:"min=20"` Password string `validate:"min=10,nefield=Name"` }

其他校验

一文读懂Go结构体标签

其他校验

ini标签

ini 是 Windows 上常用的配置文件格式, go-ini是 Go 语言中用于操作 ini 文件的第三方库。

若使用ini格式配置,需要将配置文件字段映射到结构体变量,如果键名与字段名不相同,那么需要在结构标签中指定对应的键名。标准库encoding/json、encoding/xml解析时可以将键名直接对应到字段名,而go-ini库不可以,所以需要在结构体标签指定对应键名。

示例:

## 配置文件 cnf.ini user_name = ares age = 20 // 配置文件映射 结构体 type Config struct { UserName string `ini:"user_name"` // ini标签指定下键名 Age string `ini:"age"` }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/79423.html

(0)
上一篇 2024-08-21 14:33
下一篇 2024-08-21 15:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信