Go学习第十五章——Gin参数绑定bind与验证器

news2024/11/29 4:34:22

Go web框架——Gin(参数绑定bind与验证器)

    • 1 bind参数绑定
      • 1.1 JSON参数
      • 1.2 Query参数
      • 1.3 Uri绑定动态参数
      • 1.4 ShouldBind自动绑定
    • 2 验证器
      • 2.1 常用验证器
      • 2.2 gin内置验证器
      • 2.3 自定义验证的错误信息
      • 2.4 自定义验证器

1 bind参数绑定

在Gin框架中,bind用于绑定参数,即将请求参数绑定到结构体中。通过使用bind,我们可以方便地将请求参数与结构体字段进行绑定,从而更方便地处理和验证参数。

Gin框架提供了多种绑定方法,包括Query参数绑定、Form参数绑定、JSON参数绑定等。下面分别介绍这些方法的详细用法。

Gin 提供了两种方式:1. Must Bind (不用,失败校验会返回错误) 2. Should Bind (如果校验不通过会返回错误)

1.1 JSON参数

type UserInfo struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    Sex  string `json:"sex"`
}

func main() {
    router := gin.Default()
    router.POST("/", func(c *gin.Context) {

       var userInfo UserInfo
       err := c.ShouldBindJSON(&userInfo)
       if err != nil {
          c.JSON(200, gin.H{"msg": err})
          return
       }
       c.JSON(200, userInfo)

    })
    router.Run(":8000")
}

使用apifox,提交的参数是JSON格式

{
    "name":"张三", 
    "age":21,
    "sex":"男"
}

这样响应的数据是与我们提交的参数是一样的

image-20231028164848246

1.2 Query参数

type UserInfo struct {
    Name string `json:"name" form:"name"`
    Age  int    `json:"age" form:"age"`
    Sex  string `json:"sex" form:"sex"`
}

func main() {
    router := gin.Default()

    router.POST("/query", func(c *gin.Context) {

       var userInfo UserInfo
       err := c.ShouldBindQuery(&userInfo)
       if err != nil {
          fmt.Println(err)
          c.JSON(200, gin.H{"msg": "你错了"})
          return
       }
       c.JSON(200, userInfo)

    })
    router.Run(":8000")
}

方式差不多,不多写,query参数,响应的结果跟上面一样

image-20231028165408750

1.3 Uri绑定动态参数

tag对应为uri

type UserInfo struct {
    Name string `json:"name" form:"name" uri:"name"`
    Age  int    `json:"age" form:"age" uri:"age"`
    Sex  string `json:"sex" form:"sex" uri:"sex"`
}

func main() {
    router := gin.Default()

    router.POST("/uri/:name/:age/:sex", func(c *gin.Context) {

       var userInfo UserInfo
       err := c.ShouldBindUri(&userInfo)
       if err != nil {
          fmt.Println(err)
          c.JSON(200, gin.H{"msg": "你错了"})
          return
       }
       c.JSON(200, userInfo)

    })

    router.Run(":8000")
}

注意,这里使用apifox需要传带中文参数时,要在设置这里将URL自动编码改成遵循WHATWG

image-20231028170730113

1.4 ShouldBind自动绑定

会根据请求头中的content-type去自动绑定,form-data的参数也用这个,tag用form

默认的tag就是form

绑定form-data、x-www-form-urlencode

type UserInfo struct {
    Name string `form:"name"`
    Age  int    `form:"age"`
    Sex  string `form:"sex"`
}

func main() {
    router := gin.Default()

    router.POST("/form", func(c *gin.Context) {
       var userInfo UserInfo
       err := c.ShouldBind(&userInfo)
       if err != nil {
          fmt.Println(err)
          c.JSON(200, gin.H{"msg": "你错了"})
          return
       }
       c.JSON(200, userInfo)
    })

    router.Run(":8000")
}

传的数据和响应如下:

image-20231028171520670

2 验证器

需要使用参数验证功能,需要加binding tag

2.1 常用验证器

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

2.2 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

2.3 自定义验证的错误信息

当验证不通过时,会给出错误的信息,但是原始的错误信息不太友好,不利于用户查看

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

type UserInfo struct {
  Username string `json:"username" binding:"required" msg:"用户名不能为空"`
  Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
  Email    string `json:"email" binding:"email" msg:"邮箱地址格式不正确"`
}

当出现错误时,就可以来获取出错字段上的msg。

  • err:这个参数为ShouldBindJSON返回的错误信息
  • obj:这个参数为绑定的结构体
  • 还有一点要注意的是,validator这个包要引用v10这个版本的,否则会出错

完整的代码如下:

import (
	"fmt"
	"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"`
	Email    string `json:"email" binding:"email" 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() {
	router := gin.Default()

	router.POST("/users", func(c *gin.Context) {
		var userInfo UserInfo
		err := c.ShouldBindJSON(&userInfo)
		if err != nil {
			fmt.Println(err)
			c.JSON(200, gin.H{"msg": GetValidMsg(err, &userInfo)})
			return
		}
		c.JSON(200, userInfo)
	})

	router.Run(":8000")
}

image-20231028173238176

2.4 自定义验证器

  1. 注册验证器函数
// github.com/go-playground/validator/v10
// 注意这个版本得是v10的

if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
   v.RegisterValidation("sign", signValid)
}
  1. 编写函数
// 如果用户名不等于"张三"就校验失败
func signValid(fl validator.FieldLevel) bool {
	name := fl.Field().Interface().(string)
	if name != "张三" {
		return false
	}
	return true
}
  1. 使用
package main

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
	"reflect"
)

func GetValidMsg(err error, obj interface{}) string {
	// obj为结构体指针
	getObj := reflect.TypeOf(obj)
	// 断言为具体的类型,err是一个接口
	if errs, ok := err.(validator.ValidationErrors); ok {
		for _, e := range errs {
			if f, exist := getObj.Elem().FieldByName(e.Field()); exist {
				return f.Tag.Get("msg") //错误信息不需要全部返回,当找到第一个错误的信息时,就可以结束
			}
		}
	}
	return err.Error()
}

// 如果用户名不等于"张三"就校验失败
func signValid(fl validator.FieldLevel) bool {
	name := fl.Field().Interface().(string)
	if name != "张三" {
		return false
	}
	return true
}

func main() {
	router := gin.Default()
	router.POST("/", func(c *gin.Context) {
		type UserInfo struct {
			Name string `json:"name" binding:"sign" msg:"用户名错误"`
			Age  int    `json:"age" binding:""`
		}
		var user UserInfo
		err := c.ShouldBindJSON(&user)
		if err != nil {
			// 显示自定义的错误信息
			msg := GetValidMsg(err, &user)
			c.JSON(200, gin.H{"msg": msg})
			return
		}
		c.JSON(200, user)
	})
	// 注册
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("sign", signValid)
	}
	router.Run(":8000")
}

下面我们实验一下:

image-20231028174025296

Over~~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity Meta Quest 一体机开发(三):Oculus Integration 基本原理、概念与结构+玩家角色基本配置

文章目录 📕教程说明📕输入数据📕Oculus Integration 处理手部数据的推荐流程📕VR 中交互的基本概念📕Oculus Integration 中的交互流程📕配置一个基本的玩家物体⭐OVRCameraRig⭐OVRInteraction⭐OVRHandP…

MC红显材质包安装

红显材质包安装 UP介绍视频 https://www.bilibili.com/video/BV1ML4y1u7nd/?vd_source3b8afcc2613780d7607382bae034945a 材质包下载地址: 需要 OptiFine 或 CITResewn 模组(以后还会支持其他自定义贴图模组) 下载:https://xek…

【python与数据结构】(leetcode算法预备知识)

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ python与数据结构 Python 中常见的数据类型数据结构1.数组(Array)2.链表(Linked List)3.哈希表(Hash Table)4.队列(Queue&#x…

7.多线程之单例模式

单例模式 文章目录 单例模式1. 什么是单例模式2. 饿汉模式3. 懒汉模式3.1 单线程版:3.2 多线程版 1. 什么是单例模式 单例模式是一种设计模式,常见的设计模式还有工厂模式、建造者模式等。 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码…

Java练习题2022-1

HashSet是Java中常用的Set集合,向HashSet集合中添加数据对象时,首先会调用对象的hashCode()方法获取哈希码,根据哈希码计算对象的存储位置,如果相应位置上已经有数据对象,则会调用对象的equals()方法判断新加入的对象与…

【HarmonyOS】鸿蒙操作系统架构

HarmonyOS架构 一. 鸿蒙系统定位二. 架构整体遵从分层设计三. HarmonyOS具有的技术特性四. HarmonyOS有三大特征 其它相关推荐: 软考系统架构之案例篇(架构设计相关概念) 系统架构之微服务架构 系统架构设计之微内核架构 所属专栏:系统架构设计师 一. 鸿…

分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测

分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测 目录 分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现KOA-CNN-LSTM-selfAttention开普勒算法优化卷积长短期记忆神经网络融合…

Camtasia Mac 2023版怎么给视频加字幕

在视频制作过程中,字幕和马赛克是两项非常常用的编辑功能,添加字幕可以提高观众的观看体验,添加马赛克可以保护视频创作者不想公开的画面内容。Camtasia作为一款知名的视频制作软件,在具备基本的录制和视频编辑功能的同时&#xf…

Python运维学习Day01-文件基本操作

这里写自定义目录标题 1.遍历目录下所有的文件1.1 这里主要利用os.walk 函数的功能 2. 计算文件的 MD5 值3. 我们组合下两个函数,遍历下某个文件夹下的文件的md5码 1.遍历目录下所有的文件 def getFileName(directory):file_list []for dir_name, sub_dir,file_na…

CC002:ContextCapture倾斜摄影建模流程

摘要:本文主要介绍cc倾斜摄影建模流程,包括工程创建、影像添加、任务序列路径指定、空三、像控点的导入与刺点、空三优化、三维重建、定义生产三维产品的格式等流程,其中实验数据来源为多普云职业教育平台。 一、实验数据获取 本实验使用cc软…

【深度学习】吴恩达课程笔记(三)——参数VS超参数、深度学习的实践层面

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 吴恩达课程笔记——参数VS超参数、深度学习的实践层面 六、参数VS超参数1.参数和超参数的区别2.什么是超参数?3.如何寻找超参数的最优值? 七、深度学习的实践层面1.训练 / 验证 / 测试集(T…

python 应用 之 转图片格式webp

需求:将图片转成webp格式 目录 一、python 图片转webp格式 1、安装python 2、webp 依赖的包 1)、PIP 安装Pillow 2)、VSCODE 选择python版本 2.1)、测试是否安装成功 2.2)、vscode选择python版本 3、python程序 1&#…

【深度学习】吴恩达课程笔记(二)——浅层神经网络、深层神经网络

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 笔记链接 【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础 吴恩达课程笔记——浅层神经网络、深层神经网络 四、浅层神经网络1.双层神经网络表示2.双层神经网络的前向传播第一层前向传播第二层前…

数据库简史:多主数据库架构的由来和华为参天引擎的机遇

注:本文发表后,收到了很多后台反馈,其中关于大型机的早期成就不容省略。微调重发本文,纯属个人观点,错谬之处,仍然期待指正。 2023年10月13日,在北京举办的“2023金融业数据库技术大会"上&…

前端 :用HTML和css制作一个小米官网的静态页面

1.HTML&#xff1a; <body><div id "content"><div id "box"><div id "top"><div id "top-left"><span id "logo">MI</span><span id "text-logo">小米账…

Java之数据类型与变量

目录 1. 字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.3.1 整型变量 3.3.2 长整型变量 3.3.3 短整型变量 3.3.4 字节型变量 3.4 浮点型变量 3.4.1 双精度浮点型 3.4.2 单精度浮点型 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.7…

Kafka集群修改单个Topic数据保存周期

在大数据部门经常使用Kafka集群&#xff0c;有的时候大数据部门可能在Kafka中的Topic数据保存时间不需要很长&#xff0c;一旦被消费后就不需要一直保留。默认Topic存储时间为7day&#xff0c;个别的Topic或者某台Kafka集群需要修改Topic数据保存的一个周期&#xff0c;调整为3…

攻克组合优化问题!美国DARPA选中全栈量子经典计算公司Rigetti

&#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;美国量子计算公司Rigetti宣布&#xff0c;它被美国国防高级研究计划局 (DARPA) 选中&#xff0c;加入想象未来量子实际应用 (IMPAQT) 计划&#xff0c;推进先进量子算法的研发&#xff0c;去解决组合优化问…

课题学习(九)----阅读《导向钻井工具姿态动态测量的自适应滤波方法》论文笔记

一、 引言 引言直接从原论文复制&#xff0c;大概看一下论文的关键点&#xff1a; 垂直导向钻井工具在近钻头振动和工具旋转的钻井工作状态下&#xff0c;工具姿态参数的动态测量精度不高。为此&#xff0c;通过理论分析和数值仿真&#xff0c;提出了转速补偿的算法以消除工具旋…

前端 : 用html ,css,js写一个你画我猜的游戏

1.HTML&#xff1a; <body><div id "content"><div id "box1">计时器</div><div id"box"><div id "top"><div id "box-top-left">第几题:</div><div id "box…