gin框架使用系列之五——表单校验
- 系列目录
- 《gin框架使用系列之一——快速启动和url分组》
- 《gin框架使用系列之二——uri占位符和占位符变量的获取》
- 《gin框架使用系列之三——获取表单数据》
- 《gin框架使用系列之四——json和protobuf的渲染》
一 、表单验证的基本理论
在第三篇中,我们介绍了如何将form表单和json等数据转成结构体对象中的方法,当时在绑定的结构体中,其tag中就有“binding”的信息,这就是gin中表单验证的基础。为了详细了解表单验证,我们进一步了解以下表单绑定的知识。
1.1、若要将请求体绑定到结构体中,需要使用模型绑定,支持JSON、XML、YAML和标准表单的绑定,设置时需要在绑定的字段上设置tag,其只要有两套绑定方法
-
Must bind
- 方法: Bind 、BindJSON、BindXML、BindQuery、BindYAML
- 行为:这些方法底层使用MustBindWith方法,如果存在绑定错误,请求将被终止,响应代码会被设置成400
-
Should bind
- 方法: ShouldBind、ShouldBindJSON、ShouldBindXML、ShouldBindQuery、ShouldBindYAML
- 行为:底层使用ShouldBindWith方法,如果存在绑定错误,则返回go语言的错误形式,开发人员可以处理错误,请求不会被终止
1.2、Gin中使用 go-playground/validator来验证表单,详细文档
二、表单验证示例
我们以一个注册的接口的表单验证为例,示例表单验证的写法如下:
type SignUpParam struct {// 1<= age <= 130Age uint8 `json:"age" binding:"gte=1,lte=130"`// name,必须Name string `json:"name" binding:"required"`// email,必须且满足email格式Email string `json:"email" binding:"required,email"`// password,必须Password string `json:"password" binding:"required"`// re_password,必须,且要和password字段相同RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}func main() {router := gin.Default()router.POST("/sign-up", func(c *gin.Context) {var param SignUpParamif err := c.ShouldBind(¶m); err != nil {c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error(),})return}// TODO 业务逻辑c.JSON(http.StatusOK, "success")})router.Run() // listen and serve on 0.0.0.0:8080
}
在postman中调用接口,报错信息如下:

三、表单验证信息国际化
上面示例中我们可以看到表单验证信息的报错中,显示的不是很详细,而且暴露了go后台代码的数据,我们可以为其添加国际化信息。
下面是增加翻译器的方法
func InitTrans(locale string) (err error) {//修改gin框架中的validator引擎属性, 实现定制if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//注册一个获取json的tag的自定义方法v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})zhT := zh.New() //中文翻译器enT := en.New() //英文翻译器//第一个参数是备用的语言环境,后面的参数是应该支持的语言环境uni := ut.New(enT, zhT, enT)trans, ok = uni.GetTranslator(locale)if !ok {return fmt.Errorf("uni.GetTranslator(%s)", locale)}switch locale {case "en":en_translations.RegisterDefaultTranslations(v, trans)case "zh":zh_translations.RegisterDefaultTranslations(v, trans)default:en_translations.RegisterDefaultTranslations(v, trans)}return}return
}
整体代码如下:
package mainimport ("fmt""net/http""reflect""strings""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"en_translations "github.com/go-playground/validator/v10/translations/en"zh_translations "github.com/go-playground/validator/v10/translations/zh"
)type SignUpParam struct {// 1<= age <= 130Age uint8 `json:"age" binding:"gte=1,lte=130"`// name,必须Name string `json:"name" binding:"required"`// email,必须且满足email格式Email string `json:"email" binding:"required,email"`// password,必须Password string `json:"password" binding:"required"`// re_password,必须,且要和password字段相同RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}// 定义一个全局的翻译器
var trans ut.Translatorfunc main() {//代码侵入性很强 中间件if err := InitTrans("zh"); err != nil {fmt.Println("初始化翻译器错误")return}router := gin.Default()router.POST("/sign-up", func(c *gin.Context) {var param SignUpParamif err := c.Bind(¶m); err != nil {errs, ok := err.(validator.ValidationErrors)if !ok {c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error(),})return}// 检查使用自定义的转换器c.JSON(http.StatusBadRequest, gin.H{"msg": errs.Translate(trans),})return}// TODO 业务逻辑c.JSON(http.StatusOK, "success")})router.Run() // listen and serve on 0.0.0.0:8080
}
func InitTrans(locale string) (err error) {//修改gin框架中的validator引擎属性, 实现定制if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//注册一个获取json的tag的自定义方法v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})zhT := zh.New() //中文翻译器enT := en.New() //英文翻译器//第一个参数是备用的语言环境,后面的参数是应该支持的语言环境uni := ut.New(enT, zhT, enT)trans, ok = uni.GetTranslator(locale)if !ok {return fmt.Errorf("uni.GetTranslator(%s)", locale)}switch locale {case "en":en_translations.RegisterDefaultTranslations(v, trans)case "zh":zh_translations.RegisterDefaultTranslations(v, trans)default:en_translations.RegisterDefaultTranslations(v, trans)}return}return
}
用postman输入错误信息如下:

输入全部正确信息如下:

后记
个人总结,欢迎转载、评论、批评指正
相关文章:
gin框架使用系列之五——表单校验
系列目录 《gin框架使用系列之一——快速启动和url分组》《gin框架使用系列之二——uri占位符和占位符变量的获取》《gin框架使用系列之三——获取表单数据》《gin框架使用系列之四——json和protobuf的渲染》 一 、表单验证的基本理论 在第三篇中,我们介绍了如何…...
HackTheBox - Medium - Linux - Interface
Interface Interface 是一种中等难度的 Linux 机器,具有“DomPDF”API 端点,该端点通过将“CSS”注入处理后的数据而容易受到远程命令执行的影响。“DomPDF”可以被诱骗在其字体缓存中存储带有“PHP”文件扩展名的恶意字体,然后可以通过从其…...
C++ 字符串操作说明 续
一、strstr函数 extern char *strstr(char *str1, const char *str2); 1. strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。 2. str1: 被查找目标 string …...
[情商-7]:如何回答没有标准答案的两难问题
目录 前言: 一、用“逻辑推理思维”回答两难问题 二、用“情绪思维”回答两难问题 1.1 关注提问者提出问题背后的情绪状态和情绪/情感诉求 1.2 常见的常见的情绪和情感诉求 1.3 女性情感分析 1.4 理解女性情感的语言 1.5 如何通过语言理解女性的情绪需求 三…...
对偶问题的基本性质
写于:2024年1月3日晚 修改于: 原规划与对偶规划 原规划对偶规划 max z C T X s.t. { A X ≤ b , 其中 X ( m ∗ 1 ) X ≥ 0 \begin{aligned} & \max \mathrm{z}\mathbf{C}^T \mathbf{X} \\ & \text { s.t. }\left\{\begin{array}{l}\mat…...
Google Chrome 现在会在后台扫描泄露的密码
谷歌表示,Chrome 安全检查功能将在后台运行,检查网络浏览器中保存的密码是否已被泄露。 如果桌面用户正在使用标记为危险的扩展程序(从 Chrome Web Store 中删除)、最新的 Chrome 版本,或者如果启用安全浏览来阻止 Go…...
【Matlab】PSO-BP 基于粒子群算法优化BP神经网络的数据时序预测(附代码)
资源下载: https://download.csdn.net/download/vvoennvv/88689096 目录 【Matlab】BP 神经网络时序预测算法 【Matlab】CNN卷积神经网络时序预测算法 【Matlab】ELM极限学习机时序预测算法 【Matlab】基于遗传算法优化BP神经网络 (GA-BP)的数据时序预测 【Mat…...
Linux 485驱动通信异常
背景 前段时间接到一个项目,要求用主控用485和MCU通信。将代码调试好之后,验证没问题就发给测试了。测试测的也没问题。 但是,到设备量产时,发现有几台设备功能异常。将设备拿回来排查,发现是485通信有问题ÿ…...
mybatis配置与标签大全
文章目录 mybatis配置与标签大全mybatis的配置属性(properties)设置(settings)类型别名(typeAliases)类型处理器(typeHandlers)对象工厂(objectFactory)插件&…...
Mysql的基本用法(上)非常详细、快速上手
上篇结束了java基础,本篇主要对Mysql中的一些常用的方法进行了总结,主要对查询方法进行了讲解,包括重要的多表查询用到的内连接和外连接等,以下代码可以直接复制到可视化软件中,方便阅读以及练习; SELECT *…...
使用Vite创建React + TypeScript(node版本为16.17.0,含资源下载)
PC端 安装指令: npm create vitelatest react-ts-pro -- --template react-tsVite是一个框架无关的前端工具链,可以快速的生成一个React TS的开发环境,并且可以提供快速的开发体验说明: 1. npm create vitelatest固定写法&#…...
Springboot集成RabbitMq二
接上一篇:Springboot集成RabbitMq一-CSDN博客 1、搭建项目-消费者 与之前一样 2、创建配置类 package com.wym.rabbitmqconsumer.utils;import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.spring…...
机器学习笔记 - 基于Python的不平衡数据的欠采样技术
一、简述 随着从不同的来源生成和捕获大量数据。尽管信息量巨大,但它往往反映了现实世界现象的不平衡分布。数据不平衡的问题不仅仅是统计上的挑战,它对数据驱动模型的准确性和可靠性具有深远的影响。 以金融行业欺诈检测为例。尽管我们希望避免欺诈,因为其具有高度破坏性,…...
facebook广告的基础知识
Facebook广告是在Facebook、Instagram、Audience Network等与Facebook相关的SNS和服务上投放的广告。以下是关于Facebook广告的基础知识: 广告类型: 静态图片广告:主要通过Facebook的新闻提要投放的图片广告,可以张贴产品和服务…...
java常见面试题:什么是异常?Java中的异常有哪些分类?
异常是一个汉语词语,读音为y chng,指非正常的;不同于平常的;非常。在Java中,异常(Exception)是程序在运行过程中出现的不正常情况,例如除以零、数组越界等。异常分为两大类ÿ…...
类的加载顺序问题-demo展示
面试的的时候经常会被问到包含静态代码块、实例代码块和构造器等代码结构的加载顺序问题,下面借用一个面试题,回顾一下类的代码加载顺序。 public class AooTest {public static void main(String[] args) {AooTest.f1();}static AooTest test1 new Ao…...
[蓝桥杯2020国赛]答疑
答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下: 首先进入办公室,编号为 i 的同学需要 si 毫秒的时间。然后同学问…...
【AIGC表情prompt】提示词练习技巧
表情类提示词练习技巧 医疗机器人,男人笑脸景深,数据,座标,12k,c4d渲染,高分辨率,,暖色调,高清对比 医疗机器人,男人微笑,景深,数据,座标…...
SpringBoot项目的三种创建方式
手动创建方式: ①:新建maven项目 ②:引入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version>&l…...
【docker实战】01 Linux上docker的安装
Docker CE是免费的Docker产品的新名称,Docker CE包含了完整的Docker平台,非常适合开发人员和运维团队构建容器APP。 Ubuntu 14.04/16.04(使用 apt-get 进行安装) # step 1: 安装必要的一些系统工具 sudo apt-get update sudo ap…...
实战应用:开发Win11右键菜单管理器——从快马AI生成完整项目开始
实战应用:开发Win11右键菜单管理器——从快马AI生成完整项目开始 最近帮朋友解决Win11右键菜单恢复问题,发现网上教程都是手动改注册表,既麻烦又容易出错。作为开发者,我决定用C#写个可视化工具来管理右键菜单。这个需求其实很典…...
3步打造极速安全系统:AtlasOS开源优化方案全解析
3步打造极速安全系统:AtlasOS开源优化方案全解析 【免费下载链接】Atlas 🚀 An open and lightweight modification to Windows, designed to optimize performance, privacy and security. 项目地址: https://gitcode.com/GitHub_Trending/atlas1/Atl…...
从新手到专家:OpenCore配置工具OCAT的实战应用指南
从新手到专家:OpenCore配置工具OCAT的实战应用指南 【免费下载链接】OCAuxiliaryTools Cross-platform GUI management tools for OpenCore(OCAT) 项目地址: https://gitcode.com/gh_mirrors/oc/OCAuxiliaryTools 如果你正在为黑苹果系…...
从Debezium到Flink RowData:手把手解析Flink CDC 2.3如何优雅处理MySQL的UPDATE事件
从Debezium到Flink RowData:深入解析Flink CDC 2.3处理MySQL UPDATE事件的机制 在实时数据处理的领域中,变更数据捕获(CDC)技术已经成为构建数据管道的核心组件。当MySQL数据库中的一条记录被更新时,如何准确捕获这一变更并将其高效地传递到下…...
AR.js实战指南:如何在Web浏览器中构建高效增强现实应用
AR.js实战指南:如何在Web浏览器中构建高效增强现实应用 【免费下载链接】AR.js Image tracking, Location Based AR, Marker tracking. All on the Web. 项目地址: https://gitcode.com/gh_mirrors/arj/AR.js 在移动设备普及的今天,增强现实&…...
天理与上帝——东西情理的源初图腾
天理与上帝——东西情理的源初图腾---摘要东西方文明在情理结构的根本差异,可以追溯到各自的“源初图腾”——天理与上帝。本文基于AI元人文“自感痕迹论”的框架,将天理与上帝重新理解为两种不同的“源初痕迹”或“自感显影的定向模式”。天理是“天人合…...
避坑指南:SpringBoot整合Drools 7.20时热部署冲突的解决方案
SpringBoot与Drools 7.20热部署冲突深度排查指南 当SpringBoot的devtools热部署功能遇上Drools规则引擎,就像两个高效率的工人同时修改同一台机器——看似都能独立工作,组合时却可能引发难以察觉的运行时故障。本文将带您深入这个典型的技术冲突现场&…...
# 发散创新:用 Rust实现一个轻量级游戏日引擎的核心调度机制 在现代游戏开发中,**高效的任务调度与资源管理**是性能
发散创新:用 Rust 实现一个轻量级游戏日引擎的核心调度机制 在现代游戏开发中,高效的任务调度与资源管理是性能瓶颈的关键所在。尤其是在“游戏日”这类强调多线程并行处理、实时响应的场景下,传统基于 C 或 Python 的方案往往因内存安全问题…...
TuShare实战(二)高效构建多股数据面板
1. 为什么需要多股数据面板 做量化投资的朋友都知道,数据准备是最基础也最耗时的环节。想象一下,你正在研究一个投资策略,需要同时分析5只股票的历史走势。如果每次都要单独获取、整理每只股票的数据,那效率实在太低了。这就是为什…...
别再犯这些错误!英文邮件写作中的常见误区与正确写法
英文邮件写作进阶指南:避开9个致命错误,展现专业沟通力 在跨国商务沟通中,一封得体的英文邮件就像精心设计的数字名片。我曾见证过一位工程师因为邮件中一个称呼错误,导致价值200万美元的合同谈判陷入僵局;也见过实习生…...
