gin自定义验证器+中文翻译

news2025/1/16 20:20:44

gin自定义验证器+中文翻译

    • 1、说明
    • 2、global.go
    • 3、validator.go
    • 4、eg:main.go
    • 5、调用接口测试

1、说明

gin官网自定义验证器给的例子相对比较简单,主要是语法级别,便于入门学习,并且没有给出翻译相关的处理,因此在这里记录一下通用一点的自定义验证器+中文翻译的代码,可以直接在往后的go-web项目直接使用

2、global.go

// Package global 当前包存放全局的变量,便于项目所有包使用
package global

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
)

/****************************** 全局变量 ****************************/
var (
	// Trans 全局的翻译器
	Trans ut.Translator
)

/****************************** 辅助函数 ****************************/

// removeTopStruct 移除打印的错误信息中的结构体包前缀
func removeTopStruct(fields map[string]string) map[string]string {
	rsp := map[string]string{}
	for field, err := range fields {
		rsp[field[strings.Index(field, ".")+1:]] = err
	}
	return rsp
}

// HandlerValidatorError 处理校验错误响应
func HandlerValidatorError(c *gin.Context, err error) {
	errs, ok := err.(validator.ValidationErrors)
	if !ok {
		c.JSON(http.StatusOK, gin.H{
			"msg": err.Error(),
		})
		return
	}
	c.JSON(http.StatusBadRequest, gin.H{
		"error": removeTopStruct(errs.Translate(Trans)),
	})
	return
}

3、validator.go

package validator

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"

	"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"
	entranslations "github.com/go-playground/validator/v10/translations/en"
	zhtranslations "github.com/go-playground/validator/v10/translations/zh"
)

// 验证器
var (
	trans ut.Translator
)


/****************************** 翻译器、自定义的验证器的初始化 ****************************/

// InitChineseTranslator 初始化中文翻译器
func InitChineseTranslator(){
	if err := initTrans("zh"); err != nil {
		panic("初始化翻译器错误" + err.Error())
	} else {
		fmt.Println("初始化中文翻译器成功")
	}
}

// InitEnglishTranslator 初始化英文翻译器
func InitEnglishTranslator(){
	if err := initTrans("en"); err != nil {
		panic("初始化翻译器错误" + err.Error())
	} else {
		fmt.Println("初始化英文翻译器成功")
	}
}

// initTrans 初始化翻译器
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":
			err = entranslations.RegisterDefaultTranslations(v, trans)
		case "zh":
			err = zhtranslations.RegisterDefaultTranslations(v, trans)
		default:
			err = entranslations.RegisterDefaultTranslations(v, trans)
		}
	}
	return
}

// InitValidationRules 注册自定义的验证器
func InitValidationRules() {
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 1、mobile验证器相关
		{
			// 设置自定义验证器的翻译配置,每个验证器搭配一个翻译规则
			err := v.RegisterTranslation("mobile", trans, func(ut ut.Translator) error {
				return ut.Add("mobile", "{0} 非法的手机号!", true) // see universal-translator for details
			}, func(ut ut.Translator, fe validator.FieldError) string {
				t, _ := ut.T("mobile", fe.Field())
				return t
			})
			// mobile验证器
			err = v.RegisterValidation("mobile", validateMobile)
			if err != nil {
				panic("mobile验证器注册失败:" + err.Error())
			}
		}
		//	2、XXX验证器相关
		{

		}
		fmt.Println("初始化验证器成功")
	}
}

/****************************** 自定义验证器 ****************************/

// validateMobile 手机号码的校验规则,用于gin的请求参数自动校验
func validateMobile(fl validator.FieldLevel) bool {
	// 内部通过反射获取mobile的值
	mobile := fl.Field().String()
	//使用正则表达式判断是否合法
	isValid, _ := regexp.MatchString(`^1([38][0-9]|14[579]|5[^4]|16[6]|7[1-35-8]|9[189])\d{8}$`, mobile)
	return isValid
}



/****************************** 自定义验证器 ****************************/

// validateMobile 手机号码的校验规则,用于gin的请求参数自动校验
func validateMobile(fl validator.FieldLevel) bool {
	// 内部通过反射获取mobile的值
	mobile := fl.Field().String()
	//使用正则表达式判断是否合法
	isValid, _ := regexp.MatchString(`^1([38][0-9]|14[579]|5[^4]|16[6]|7[1-35-8]|9[189])\d{8}$`, mobile)
	return isValid
}

4、eg:main.go

使用样例,需要在main函数中先调用validator包中的函数,初始化翻译器跟验证器
在接口解析参数的地方,判断处理验证异常

package main

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"

	// 引入全局的校验异常处理函数
	"Go_Bible/valiator_test/global"
	// 引入通用的验证器相关代码
	"Go_Bible/valiator_test/validator"
)

/****************************** 表单结构体、配置校验约束 ****************************/

// PasswordLoginForm 用户名、密码登录表单结构体
type PasswordLoginForm struct {
	Mobile   string `form:"mobile" json:"mobile" binding:"required,mobile"` // 自定义了mobile验证器,使用自定义的校验规则
	Password string `form:"password" json:"password" binding:"required,min=3,max=10"`
}

/****************************** 接口实现 ****************************/

// Login 登录接口
func Login(c *gin.Context) {
	passwordLoginForm := PasswordLoginForm{}
	// 解析form参数或者json参数
	if err := c.ShouldBindJSON(&passwordLoginForm); err != nil {
		// 处理验证异常
		global.HandlerValidatorError(c, err)
		return
	}
	fmt.Println("参数通过验证,登录接口请求参数:", passwordLoginForm)
	c.JSON(http.StatusOK, gin.H{
		"msg": passwordLoginForm,
	})
}

/****************************** 主函数 ****************************/
func main() {
	// 1、初始化中文翻译器
	validator.InitChineseTranslator()
	// 2、初始化自定义的验证器+验证信息翻译
	validator.InitValidationRules()

	// 3、初始化gin路由配置
	router := gin.Default()
	router.POST("/login", Login)
	fmt.Println("Gin启动")
	if err := router.Run(":8081"); err != nil {
		panic("Gin启动错误:" + err.Error())
	}
}

5、调用接口测试

启动main.go,发送请求测试接口:http://127.0.0.1:8081/login

在这里插入图片描述

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

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

相关文章

Windows离线安装snmp服务

打开1里面有教程 选择“管理” 启动,发现不行 再把2拷贝到: 在启动就可以了(查看服务:ctrlshiftEsc)

JUC下的Java java.util.concurrent.Locks详解

java.util.concurrent.locks 包介绍 java.util.concurrent.locks 包是Java并发编程中非常重要的一个部分,它提供了比内置synchronized关键字更为灵活的锁机制,用于多线程环境下的同步控制。这个包中最核心的是Lock接口,以及一系列实现类&…

17 SPI FLASH读写

SPI 协议简介 SPI 即 Serial Periphera linterface 的缩写,顾名思义就是串行外围设备接口,主要用于与FLASH、实时时钟、AD 转换器等外设模块的通信,它是一种高速的全双工同步的通信总线。 SPI 设备分为主设备和从设备,SPI 通信必…

vs code中如何使用git

由于本地代码有了一些储备,所以想通过网址托管形式,之前一直使用了github,但是鉴于一直被墙,无法登录账号,所以选择了国内的gitee来作为托管网站。 gitee的网址:Gitee - 基于 Git 的代码托管和研发协作平台…

蓝桥杯-网络安全比赛(7)基础知识 HTTP、TTL、IP数据包、MSS、MTU、ARP、LLMNR、MDNS、NBNS。

1. IP中TTL值能够给我提供什么信息?2. IP头部中标志、13位偏移、32位源IP地址、目标IP、IP数据包格式,有多少字节3. IP头部中的16位标识是什么?4. MSS 和MTU分别有多大?5. 怎么获取路由IP信息?PING、NSLOOKUP、TRACERT…

记忆化搜索专题

前言 如果要记忆化搜索的话&#xff0c;如果数据是10的九次方&#xff0c;我们不可能开一个那么大的数组来存储&#xff0c;所以我们要学会用map来存储 leecode1553 class Solution {unordered_map<int, int> memo; public:int minDays(int n) {if (n < 1) {return n;…

渗透测试-信息收集

网络安全信息收集是网络安全领域中至关重要的一环&#xff0c;它涉及到对目标系统、网络或应用进行全面而细致的信息搜集和分析。这一过程不仅有助于理解目标网络的结构、配置和潜在的安全风险&#xff0c;还能为后续的渗透测试、风险评估和安全加固提供有力的支持。 在网络安…

linux_用户与组

用户与组 基于账号的访问控制 账号类型&#xff1a;用户账号(UID) 、组账号(GID) 用户账号简介 作用: 1.可以登陆操作系统 2.不同的用户具备不同的权限 唯一标识&#xff1a;UID&#xff08;编号从0开始的编号&#xff0c;默认最大60000&#xff09; 管理员root的UID&…

鸿蒙开发接口Ability框架:【(AbilityContext)】

AbilityContext AbilityContext是Ability的上下文环境&#xff0c;继承自Context。 AbilityContext模块提供允许访问特定于ability的资源的能力&#xff0c;包括对Ability的启动、停止的设置、获取caller通信接口、拉起弹窗请求用户授权等。 说明&#xff1a; 本模块首批接口…

算法设计与分析 例题 绘制Huffman树、循环赛、分治、最短路与动态规划

1.考虑用哈夫曼算法来找字符a,b,c,d,e,f 的最优编码。这些字符出现在文件中 的频数之比为 20:10:6:4:44:16。要求&#xff1a; &#xff08;1&#xff09;&#xff08;4 分&#xff09;简述使用哈夫曼算法构造最优编码的基本步骤&#xff1b; &#xff08;2&#xff09;&…

代码已经推送到远程,如何退回之前的提交记录

现状&#xff1a;代码已经推送到远程&#xff0c;如何退回之前的提交记录 Sourcetree工具实现 最后使用命令强制推送&#xff1a; git push origin dev --forceidea 工具实现 强行推送

网络编程学习笔记1

文章目录 一、socket1、创建socket2、网络通信流程3、accept()函数4、signal()函数5、recv()函数6、connect()函数 二、I/O多路复用1.select模型2.poll模型3.epoll模型 注 一、socket 1、创建socket int socket(int domain,int type,int protocol); //返回值&#xff1a;一个…

ssm120基于SSM框架的金鱼销售平台的开发和实现+jsp

金鱼销售平台 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于金鱼销售平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了金鱼销售平台&#xff0c;它彻底改…

电商平台商品数据的价值在哪里?如何实现批量抓取?

一、电商平台商品数据的价值探秘 在数字经济的浪潮中&#xff0c;电商平台商品数据如同一座蕴藏着无尽宝藏的矿山&#xff0c;其价值远超过我们表面的认知。今天&#xff0c;就让我们一起揭开这座矿山的神秘面纱&#xff0c;探寻其中的奥秘。 首先&#xff0c;电商平台商品数…

FPGA第2篇,FPGA与CPU GPU APU DSP NPU TPU 之间的关系与区别

简介&#xff1a;首先&#xff0c;FPGA与CPU GPU APU NPU TPU DSP这些不同类型的处理器&#xff0c;可以被统称为"处理器"或者"加速器"。它们在计算机硬件系统中承担着核心的计算和处理任务&#xff0c;可以说是系统的"大脑"和"加速引擎&qu…

AI算法-高数5-线性代数1-基本概念、向量

线性代数&#xff1a;主要研究1、张量>CV计算机视觉 2、研究张量的线性关系。 深度学习的表现之所以能够超过传统的机器学习算法离不开神经网络&#xff0c;然而神经网络最基本的数据结构就是向量和矩阵&#xff0c;神经网络的输入是向量&#xff0c;然后通过每个矩阵对向量…

自动驾驶技术与传感器数据处理

目录 自动驾驶总体架构 感知系统 决策系统 定位系统 ​计算平台​ 仿真平台​ 自动驾驶公开数据集 激光点云 点云表征方式 1) 原始点云 2) 三维点云体素化 3)深度图 4)鸟瞰图 点云检测障碍物的步骤 PCL点云库 车载毫米波雷达 车载相机 设备标定 自动驾驶…

DMA原理、传输过程及传输方式

1.DMA DMA(Direct Memory Access&#xff0c;直接存储器访问)&#xff0c;是硬件实现存储器与存储器之间或存储器与I/O设备之间直接进行数据传输的内存技术&#xff0c;它允许不同速度的硬件设备(外设到内存、内存到外设、内存到内存、外设到外设)进行沟通&#xff0c;而不需要…

MySQL相关文件的介绍

其中的pid-file/var/run/mysqld/mysqld.pid是用来定义MySQL的进程ID的信息的&#xff0c; 这个ID是操作系统分配给MySQL服务进程的唯一标识&#xff0c;使得系统管理员可以轻松识别和管理该进程。 其中的log-error/var/log/mysqld.log是MySQL的错误日志文件&#xff0c;如果有…

C++string 类的常用方法

string (构造函数) (1) default 构造长度为零字符的空字符串。 (2) copy 构造 str 的副本。 (3) substring 复制从字符位置 pos 开始并跨越 len 字符的 str 部分&#xff08;如果任一 str 太短或 len 为 string&#xff1a;&#xff1a;npos&#xff0c;则复制 str 的末尾…