「容器管理系统」开发篇:4. Gin 如何优雅的使用 struct 的 tag 标签
回顾
项目已开源:基于 Golang 的 容器管理系统
Gin
请求参数绑定解读
在使用 Gin Web
框架时,接收参数一般是这样操作:
- 定义接收参数的
struct
结构体
type ParamsRequest struct{
UserName string `json:"user_name" form:"user_name"`
...
}
- 使用
ShouldBind
系列函数,对接收的struct
结构体进行赋值,会识别struct
中的tag
标签
ShouldBind
系列函数包含:
ShouldBind、ShouldBindJSON、ShouldBindXML、ShouldBindQuery、ShouldBindYAML、ShouldBindTOML、ShouldBindHeader、ShouldBindUri、ShouldBindWith、ShouldBindBodyWith
这 10 个函数,用来获取各种格式的请求。使用方式可以参考 Gin 源码 context.go 这个文件。
这里咱们就主要讲解前两个函数: ShouldBind
、ShouldBindJSON
注意:
ShouldBind
系列函数 会默认识别form tag
标签,如果没有设置form tag
标签,会退而求其次,识别json tag
标签,如果根本就没有设置tag
, 会使用struct
的属性名
所以:在请求传参时,需要根据
struct
的tag
标签的名字进行传参才会识别到数据,进行赋值
ShouldBind
是一个通用获取,可以根据请求类型和请求的内容类型Content-Type
来自动识别是什么格式的请求,走对应的格式进行赋值,一般不指定请求格式的就使用这个
var params ParamsRequest
if err := c.ShouldBind(¶ms); err != nil {
return
}
ShouldBindJSON
是用来专门获取json
请求的,前置条件是:struct
中 设置对应的json tag
标签
var params ParamsRequest
if err := c.ShouldBindJSON(¶ms); err != nil {
return
}
项目中咱们使用的:ShouldBindJSON
, 通过上面的解读,是不是认为 Gin
的参数获取已经做得很好了,可以直接进行赋值拿到了,下面直接用就好了,话是这么说,在这里我提出一个问题: 拿到参数之后,对数据库操作,你会在怎么做呢?
如何操作 struct
的 tag
?
这里有以下方法可以操作:
- 通过官方
reflect
反射包解析tag
标签
func ToTags(c any, tagName string) (fields []string) {
tagFields := []reflect.StructField{}
ct := reflect.TypeOf(c)
for i := 0; i < ct.NumField(); i++ {
tagFields = append(tagFields, ct.Field(i))
}
for _, val := range tagFields {
tagValue := val.Tag.Get(tagName)
if tagValue != "" {
fields = append(fields, strings.Split(tagValue, ",")[0])
}
}
return fields
}
structs.ToTags(any, "json")
上面这段代码可以解析到
tag
标签,并返回出一个 字符数组进行接收,但是你解析出来之后,如何对你定义的数据库model
的struct
进行赋值呢?
如何将传参的 struct
优雅的赋值到 model
的 struct
中?
这里使用到了
encoding/json
官方JSON
包
- 定义一个
model struct
和params struct
type ParamsRequest struct {
IdOne uint32 `json:"id_one"`
IdTwo string `json:"id_two"`
}
type ModelStruct struct {
IdOne uint32 `json:"id_one"`
IdTwo uint32 `json:"id_two"`
}
- 实现函数:
func (c *ModelStruct) ParseFields(p any) *ModelStruct {
if p == nil {
return c
}
pjson, err := json.Marshal(p)
if err != nil {
return c
}
err = json.Unmarshal(pjson, c)
if err != nil {
return c
}
return c
}
解析步骤:
- 第一步: 使用
json.Marshal
将params struct
转换为params []byte
- 第二步: 使用
json.Unmarshal
将params []byte
转换为model struct
- 第三步: 重新返回
model struct
(这一步是返回新的model struct
避免重复赋值)
结束语
- 使用了
encoding/json
包的特性:json.Marshal、json.Unmarshal
json.Marshal
可以将指定的struct
序列化成json
格式的数据json.Unmarshal
可以将任意json
格式的数据转换到指定的struct
这里的
struct
不规定是同一个,可以使用不同的struct
进行相互转换,只要对应的struct
有对应的属性和tag
标签,就可以识别到。
转载自:https://juejin.cn/post/7291935623477362715