Day04:Gin框架快速入门03 bind绑定器| 青训营(二)

简介: Day04:Gin框架快速入门03 bind绑定器| 青训营

常用验证器

// 不能为空,并且不能没有这个字段
required: 必填字段,如:binding:"required"  
// 针对字符串的长度
min 最小长度,如:binding:"min=5"
max 最大长度,如:binding:"max=10"
len 长度,如:binding:"len=6"
// 针对数字的大小
eq 等于,如:binding:"eq=3"
ne 不等于,如:binding:"ne=12"
gt 大于,如:binding:"gt=10"
gte 大于等于,如:binding:"gte=10"
lt 小于,如:binding:"lt=10"
lte 小于等于,如:binding:"lte=10"
// 针对同级字段的
eqfield 等于其他字段的值,如:PassWord string `binding:"eqfield=Password"`
nefield 不等于其他字段的值
- 忽略字段,如:binding:"-"

我们重新改变一下结构体的代码

type User struct {  
Name string `form:"name" binding:"required"`  
Age int `form:"age" binding:"min=18"`  
Gender int `form:"gender" binding:"len=1"`  
} //一个user简单的user结构体

运行之后就会按照上面的验证。 postman运行结果如下

1:全部正常

image.png

2: name不写

image.png

3:age<18

image.png

4:genderlen>1

image.png

当有多个不符合时,只会报道第一个发现的error

Gin自带的验证器

// 枚举  只能是red 或green
oneof=red green 
// 字符串  
contains=fengfeng  // 包含fengfeng的字符串
excludes // 不包含
startswith  // 字符串前缀
endswith  // 字符串后缀
// 数组
dive  // dive后面的验证就是针对数组中的每一个元素
// 网络验证
ip
ipv4
ipv6
uri
url
// uri 在于I(Identifier)是统一资源标示符,可以唯一标识一个资源。
// url 在于Locater,是统一资源定位符,提供找到该资源的确切路径
// 日期验证  1月2号下午3点4分5秒在2006年
datetime=2006-01-02

与常用验证器使用方法一致,鼓励读者自己去运行测试,其实非常简单,只能说一模一样。

自定义验证的错误信息

我们上面的代码运行过后,当测试失败案例时,返回的meg往往不够明显,所以我们可以自定义验证错误信息,也就是当出现我们预料到的情况时返回给前端。

只需要给结构体加一个msg 的tag。

type User struct {  
Name string `form:"name" binding:"required" msg:"name没有填写"`  
Age int `form:"age" binding:"min=18"`  
Gender int `form:"gender" binding:"len=1"`  
} //一个user简单的user结构体

之后我们需要获取msg中的信息,这里我们自定义一个方法来获得 当元素不符合需求时,返回标签中的信息

// GetValidMsg 返回结构体中的msg参数  
func GetValidMsg(err error, obj any) string {  
// 使用的时候,需要传obj的指针  
getObj := reflect.TypeOf(obj)  
// 将err接口断言为具体类型  
if errs, ok := err.(validator.ValidationErrors); ok {  
// 断言成功  
for _, e := range errs {  
// 循环每一个错误信息  
// 根据报错字段名,获取结构体的具体字段  
if f, exits := getObj.Elem().FieldByName(e.Field()); exits {  
msg := f.Tag.Get("msg")  
return msg  
}  
}  
}  
return err.Error()  
}

GetValidMsg 函数的作用是从结构体的字段中获取 msg 参数,并返回错误信息。

函数签名为:

func GetValidMsg(err error, obj any) string

参数说明:

  • err 是一个错误类型,用于接收验证错误信息。
  • obj 是一个任意类型,需要传入结构体的指针。

函数内部实现的逻辑如下:

  1. 通过 reflect.TypeOf(obj) 获取传入对象的具体类型。
  2. err 断言为 validator.ValidationErrors 类型,用于验证是否为验证错误。
  3. 如果断言成功,则表示错误是由验证器返回的。
  4. 遍历每一个错误信息,通过报错字段名获取结构体中对应的字段。
  5. 如果找到了对应的字段,则通过 Tag.Get("msg") 获取字段的 msg 参数。
  6. 返回 msg 参数作为错误提示信息。
  7. 如果没有找到对应的字段,则返回原始错误信息 err.Error()

内部方法解答:

1:

validator.ValidationErrors 是一个类型,它表示验证器返回的错误信息。

如果 errvalidator.ValidationErrors 类型或其子类型,则转换成功, ok     的值将为 true,同时将转换后的结果赋值给 errs

getObj.Elem().FieldByName(e.Field()) 这段代码用于根据报错字段名获取结构体的具体字段。

2:

  • getObj 是一个 reflect.Type 类型的变量,表示传入对象的类型。
  • getObj.Elem() 方法返回 getObj 的指针所指向的具体类型。
  • FieldByName(name string) reflect.StructField 方法会返回一个 reflect.StructField 类型的值,该值描述了结构体的一个字段。参数 name 表示字段的名称,该方法会根据名称在结构体中查找并返回对应的字段。
  • e.Field() 返回验证错误的字段名。

因此,getObj.Elem().FieldByName(e.Field()) 的作用是根据报错字段名,在结构体中查找并返回对应的字段的描述信息(reflect.StructField 类型)。

完整代码

package main  
import (  
"github.com/gin-gonic/gin" //引入框架  
"github.com/go-playground/validator/v10"  
"net/http"  
"reflect"  
)  
type User struct {  
Name string `form:"name" binding:"required" msg:"name没有填写"`  
Age int `form:"age" binding:"min=18"`  
Gender int `form:"gender" binding:"len=1"`  
} //一个user简单的user结构体  
// GetValidMsg 返回结构体中的msg参数  
func GetValidMsg(err error, obj any) string {  
// 使用的时候,需要传obj的指针  
getObj := reflect.TypeOf(obj)  
// 将err接口断言为具体类型  
if errs, ok := err.(validator.ValidationErrors); ok {  
// 断言成功  
for _, e := range errs {  
// 循环每一个错误信息  
// 根据报错字段名,获取结构体的具体字段  
if f, exits := getObj.Elem().FieldByName(e.Field()); exits {  
msg := f.Tag.Get("msg")  
return msg  
}  
}  
}  
return err.Error()  
}  
func get(c *gin.Context) {  
var user User  
if err := c.ShouldBind(&user); err != nil {  
c.JSON(http.StatusBadRequest, gin.H{"msg": GetValidMsg(err, &user)}) //绑定失败,返回错误信息  
return  
}  
c.JSON(http.StatusOK, gin.H{"message": "响应成功", "user": user}) //绑定成功,响应user  
}  
func main() {  
router := gin.Default() //设置路由  
router.GET("/form", get)  
router.Run() //设置运行接口  
}

之后我们在postman里故意不写name,将会给出我们的msg:

image.png

相关文章
|
SQL 前端开发 安全
Gin-Vue-Admin 使用 gin+vue 进行极速开发的全栈开发基础平台【gva 第一节】
功能: 1.增加了 pgsql 数据库初始化,用户可选用 pgsql 进行开发。 2.增加了业务数据库功能,用户可通过 yaml 中配置自己的业务数据库,根据 name 获取业务库进行业务操作,实现框架和业务的数据库分离。 3.oss 集成了华为云 oss。 4.前端打包增加了提示内存不足时的一键 node 内存扩容 build 命令。 5.调整了获取用户信息的方法,增加了不鉴权模式下的用户信息获取方式。 6.配置页面调整。 7.取消了自动化代码中数据库类型和 size 的选择模块,防止自动化代码报错。
526 0
|
前端开发 应用服务中间件 数据库
Python编程入门实战:打造你的第一个Web应用
Python编程入门实战:打造你的第一个Web应用
53 0
|
存储 前端开发 安全
Spring Boot + vue-element 开发个人博客项目实战教程(十七、登录功能实现(下))1
Spring Boot + vue-element 开发个人博客项目实战教程(十七、登录功能实现(下))1
81 1
Spring Boot + vue-element 开发个人博客项目实战教程(十七、登录功能实现(下))1
|
前端开发 中间件 Java
Day05:Gin框架快速入门05 中间件和路由 | 青训营
Day05:Gin框架快速入门05 中间件和路由 | 青训营
|
XML JSON 程序员
Day04:Gin框架快速入门03 bind绑定器| 青训营(一)
Day04:Gin框架快速入门03 bind绑定器| 青训营
|
前端开发 JavaScript NoSQL
Spring Boot + vue-element 开发个人博客项目实战教程(十六、登录功能实现(上))1
Spring Boot + vue-element 开发个人博客项目实战教程(十六、登录功能实现(上))1
163 1
|
XML SQL 前端开发
Spring Boot + vue-element 开发个人博客项目实战教程(二十四、文章管理页面开发(3))
Spring Boot + vue-element 开发个人博客项目实战教程(二十四、文章管理页面开发(3))
76 0
Spring Boot + vue-element 开发个人博客项目实战教程(二十四、文章管理页面开发(3))
|
JSON 缓存 程序员
Day04:Gin框架快速入门02 请求| 青训营
Day04:Gin框架快速入门02 请求| 青训营
|
XML JSON 前端开发
Day03:Gin框架快速入门01 响应| 青训营
Day03:Gin框架快速入门01 响应| 青训营
|
前端开发 NoSQL Java
Spring Boot + vue-element 开发个人博客项目实战教程(二十二、文章管理页面开发(1))
Spring Boot + vue-element 开发个人博客项目实战教程(二十二、文章管理页面开发(1))
92 0
下一篇
无影云桌面