gin框架学习笔记(四) ——参数绑定与参数验证

参数绑定

前言

在Gin框架中我们可以利用bind来将前段传递过来的参数与结构体进行参数绑定与参数校验,而这bind的方式主要有以下两种:

  • Mustbind:一般使用较少,因为参数校验失败会改变状态码
  • Shouldbind:主要使用上的校验方法,校验失败的话会返回错误

Shouldbind绑定相关参数

  • 绑定Json参数
package mainimport ("fmt""github.com/gin-gonic/gin"
)type UserInfo struct {Username string `json:"username"`Age      int    `json:"age"`Sex      string `json:"sex"`
}func main() {r := gin.Default()r.POST("/json", func(c *gin.Context) {var user UserInfoerr := c.ShouldBindJSON(&user)if err != nil {fmt.Println("err:", err)c.JSON(200, gin.H{"code":    400,"message": "请求参数错误",})return}c.JSON(200, user)})r.Run(":8080")
}

这里我的侧是主要是两方面,一个是看参数错误的返回,一个是参数正确的返回:
在这里插入图片描述
在这里插入图片描述

  • 绑定查询参数
package mainimport ("fmt""github.com/gin-gonic/gin"
)
type UserInfo_Query struct {Username string `json:"username" form:"username"`Age      int    `json:"age" form:"age"`Sex      string `json:"sex" form:"sex"`
}func main() {r := gin.Default()r.GET("/query", func(c *gin.Context) {var user UserInfo_Queryerr := c.ShouldBindQuery(&user)if err != nil {fmt.Println("err:", err)c.JSON(200, gin.H{"code":    400,"message": "请求参数错误",})return}c.JSON(200, user)})r.Run(":8080")
}

运行结果:
在这里插入图片描述
在这里插入图片描述

  • 绑定url参数
package mainimport ("fmt""github.com/gin-gonic/gin"
)type UserInfo_Uri struct {Username string `json:"username" form:"username" uri:"username"`Age      int    `json:"age" form:"age" uri:"age"`Sex      string `json:"sex" form:"sex" uri:"sex"`
}
func main() {r := gin.Default()r.POST("/uri/:username/:age/:sex", func(c *gin.Context) {var user UserInfo_Urierr := c.ShouldBindUri(&user)if err != nil {fmt.Println("err:", err)c.JSON(200, gin.H{"code":    400,"message": "请求参数错误",})return}c.JSON(200, user)})r.Run(":8080")
}

在这里插入图片描述

  • 绑定表单参数
package mainimport ("fmt""github.com/gin-gonic/gin"
)type UserInfo_Form struct {Username string `json:"username" form:"username"`Age      int    `json:"age" form:"age"`Sex      string `json:"sex" form:"sex"`
}func main() {r := gin.Default()r.POST("/form", func(c *gin.Context) {var user UserInfo_Formerr := c.ShouldBind(&user)if err != nil {fmt.Println("err:", err)c.JSON(200, gin.H{"code":    400,"message": "请求参数错误",})return}c.JSON(200, user)})r.Run(":8080")
}

运行结果:
在这里插入图片描述

bind绑定器

正文前的碎碎念

我们在上面介绍了很多绑定参数的方法,我们可以通过它们将一些前端传递锅里的参数存储到结构体中,进而让我们去使用,但是我们在日常生活其实并没有这么简单,博主举一个简单的例子:博主小时候玩游戏的时候要申请账号,小时候博主很喜欢玩赛尔号,但是博主只有暑假才能玩,当时老是记不住密码。试过把密码抄在书上,但是老是忘了抄在哪里,当时想把密码就设成111它又不让,当时还差点给气哭来着(呜呜呜),那现在有一个问题,这种对密码的限制是怎么做到的呢?这就提到参数绑定了,让我们跟随赛尔号开始今天的内容了!
在这里插入图片描述

参数验证

在我们设置参数验证的时候,需要加binding tag

  • 常见验证器
    在我们说常见验证器的具体内容之前我先来演示一下验证器的作用,假如我们现在有一个密码注册页面,我们要求年龄在18岁以上,密码长度在6位以上,我们可以这么写:
package mainimport ("github.com/gin-gonic/gin""net/http"
)type User_enroll struct {Username string `json:"username" form:"username"`Age      int    `json:"age"  form:"age" binding:"gt=18"`Sex      string `json:"sex"  form:"sex"`Password string `json:"password" form:"password" binding:"min=8"`
}func main() {r := gin.Default()r.POST("/user", func(c *gin.Context) {var user User_enrollif err := c.ShouldBind(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}c.JSON(200, user)})r.Run(":8080")
}

我们正常按照要求输入是可以正常返回的:
在这里插入图片描述
但是不按照binding要求的话,返回是这样的:
在这里插入图片描述
除此之外,常见验证器还有其他的限制条件表示方法,如下:

// 不能为空,并且不能没有这个字段
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:"-"

内置验证器

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

自定义验证器

自定义验证的错误消息

当我们验证参数出现错误的时候,原生的错误信息有时候并不是很友好,我们可以自己去定义返回的错误消息,示例如下:

package mainimport ("github.com/gin-gonic/gin""github.com/go-playground/validator/v10""reflect"
)type UserInfo struct {Username string `json:"username" binding:"required" msg:"用户名不能为空"`Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
}// 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 main() {r := gin.Default()r.POST("/user", func(c *gin.Context) {var user UserInfoerr := c.ShouldBindJSON(&user)if err != nil {c.JSON(400, gin.H{"msg": _GetValidMsg(err, &user)})return}c.JSON(200, user)})r.Run(":8080")
}

运行测试:
在这里插入图片描述

自定义验证器

  • 注册验证器函数
//注册验证器函数if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("sign", signValid)}r.Run(":8080")
  • 验证器函数的躯体实现:
func signValid(fl validator.FieldLevel) bool {// 获取字段值value := fl.Field().Interface().(string)// 验证规则if value == "fengxu" {return false}return true
}
  • 调用函数
type UserInfo struct {Username string `json:"username" binding:"sign" msg:"用户名设置错误"`Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
}

完整代码:

package mainimport ("github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""github.com/go-playground/validator/v10""reflect"
)type UserInfo struct {Username string `json:"username" binding:"sign" msg:"用户名设置错误"`Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
}// 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 signValid(fl validator.FieldLevel) bool {// 获取字段值value := fl.Field().Interface().(string)// 验证规则if value == "fengxu" {return false}return true
}func main() {r := gin.Default()r.POST("/user", func(c *gin.Context) {var user UserInfoerr := c.ShouldBindJSON(&user)if err != nil {c.JSON(400, gin.H{"msg": _GetValidMsg(err, &user)})return}c.JSON(200, user)})//注册验证器函数if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("sign", signValid)}r.Run(":8080")
}

运行测试:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/706947.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

股指期货基差对哪类策略影响最大?

股指期货的基差对市场中性策略的业绩影响最大。市场中性策略是一种旨在通过同时持有多头和空头仓位来对冲市场风险的策略,从而在各种市场环境下都能获得稳定的收益。在这类策略中,投资者通常会买入一篮子股票(多头仓位)&#xff0…

沃尔玛自建自养号测评的优势,提升产品排名的新选择

在沃尔玛平台上,产品排名和销量的提升对于卖家而言至关重要,而产品测评则是实现这一目标的有效途径。然而,市场上对于测评的需求激增,随之而来的是寻找测评服务的种种困难和风险。因此,越来越多的卖家选择自建自养号测…

uniapp微信小程序使用vscode代替HBuilderX开发uniapp微信小程序并且vscode改动代码微信开发者工具能实时更新

前言 最近公司开发新的小程序项目,经调研综合所有人员考虑,用uni-app Vue3tsvite技术栈开发;而官方推荐使用HBuilderX开发,而考虑到目前公司所有前端人员对VsCode更熟悉,故此总结了一下uniapp项目使用vscode代替HBuild…

vue嵌套路由

一、嵌套 children配置 1.父类路由 mymusic 2.子类路由 musicson 1.创建MusicSon组件 <template><div><p>从前和后来</p><p>唯一</p><p>运气来的似有若无</p></div> </template><script>export defaul…

中年阿里,贵在折腾

文丨黄小艺 马云的那句“阿里会改”&#xff0c;正在被吴泳铭变成“阿里爆改”。 5月14日&#xff0c;阿里巴巴发布2024年三月底止季度及2024财务年度业绩公告。据公告显示&#xff0c;截至2024年3月31日止财务年度&#xff0c;阿里巴巴收入为人民币9411.68亿元&#xff0c;同…

【资源汇总】GIS/RS相关软件包+数据分享(直接获取附链接)

01软件类 ArcGIS 10.2 链接&#xff1a;https://pan.baidu.com/s/1euHa3eTiaTjiOu-zxsi9eA?pwdnjov ArcGIS Pro 2.8.6 链接&#xff1a;https://pan.baidu.com/s/1Y3AQshCGL7tA1zdUc7s9PQ?pwdlkic ENVI 5.3 链接&#xff1a;https://pan.baidu.com/s/14k4IVlYIheNOr2to…

财富加速器!AI智能无人直播,矩阵操作引领您卖货、卖团购券、拓客,助力财富梦想实现!

财富加速器&#xff01;AI智能无人直播&#xff0c;矩阵操作引领您卖货、卖团购券、拓客&#xff0c;助力财富梦想实现&#xff01; 在当今数字化时代&#xff0c;AI智能技术正以惊人的力量催生新的商机&#xff0c;为经济增长注入源源不断的动力。如果您渴望实现财富梦想&…

Spring框架学习笔记(三):AOP编程

1 动态代理 1.1 通过案例理解动态代理 &#xff08;1&#xff09;需求说明&#xff1a; 1. 有 Vehicle接口(交通工具接口, 有一个 run 方法), 下面有两个实现类 Car 和 Ship 2. 当运行 Car 对象 的 run 方法和 Ship 对象的 run 方法时&#xff0c;输入如下内容, 注意观察前后…

Linux上编译安装和卸载软件

在maven官网下载maven时候&#xff0c;看到maven-3.9.5这个版本有2份安装包&#xff0c;一个是binaries&#xff0c;一个是source binaries是已编译好的文件&#xff0c;可以直接使用的版本&#xff1b;source是源代码版本&#xff0c;需要自己编译 源码的安装一般由这三个步…

Codec-SUPERB @ SLT 2024: 编解码器语音处理通用性能基准

作者&#xff1a;Codec-SUPERB team 比赛注册&#xff1a;https://forms.gle/sBRB4VsoDKkNYQQ98 论文链接&#xff1a;https://arxiv.org/abs/2402.13071 比赛网站: https://codecsuperb.github.io/ 公开资料集提交 Evaluation 结果: https://github.com/voidful/Codec-SUP…

后端之路第二站(正片)——SprintBoot

前提&#xff1a;得会基础java和一点maven 前言&#xff1a;不知道出于什么原因&#xff0c;可能是喜欢犯贱吧&#xff0c;本人从大一到大二都一直在专研前端开发&#xff0c;一点也没接触过后端&#xff0c;但是突然抽风想学后端了&#xff0c;想试着自己全栈搞一下项目&#…