当前位置: 首页 > ai >正文

Gin Validator 错误信息翻译与自定义校验规则详解

前言

在使用 Go 语言的 Gin 框架开发 Web 应用时,数据校验是保障接口数据完整性和安全性的关键环节。Gin 集成了 go-playground/validator/v10 作为其默认的校验引擎,提供了强大且灵活的结构体字段验证能力。然而,其默认的英文错误信息对中文用户不够友好,且内置规则无法覆盖所有业务场景。

本文将深入探讨 Gin Validator 的两大核心功能:错误信息的翻译(国际化) 和 自定义校验规则的实现,帮助你构建更健壮、更用户友好的 API 接口。

一、前置准备

确保项目中已安装必要的依赖:

go get -u github.com/gin-gonic/gin
go get -u github.com/go-playground/validator/v10
go get -u github.com/go-playground/validator/v10/translations/zh

说明:zh 包用于支持中文翻译。

二、基础校验回顾

Gin 使用结构体标签(binding)进行数据校验。例如:

type LoginReq struct {Username string `json:"username" binding:"required,min=3,max=11"`Password string `json:"password" binding:"required,min=6"`
}

当数据不满足规则时,Gin 会返回类似 "Key: 'LoginReq.Username' Error:Field validation for 'Username' failed on the 'required' tag" 的英文错误信息。我们需要将其转换为中文,并支持自定义规则。
在这里插入图片描述

三、错误信息翻译(国际化)

为了让错误提示更友好,我们需要将默认的英文错误信息翻译成中文。

1. 初始化翻译器

首先,我们需要创建一个翻译器实例,并注册中文翻译支持。

import ("errors""gin/global""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""reflect""strings"
)func InitTrans(locale string) (err error) {if v, ok := binding.Validator.Engine().(*validator.Validate); ok {zh := zh.New()en := en.New()uni := ut.New(zh, en)// 获取翻译器global.Trans, ok = uni.GetTranslator(locale)if !ok {return errors.New("不支持的语言:" + locale)}switch locale {case "zh":err = zh_translations.RegisterDefaultTranslations(v, global.Trans)case "en":err = en_translations.RegisterDefaultTranslations(v, global.Trans)default:err = zh_translations.RegisterDefaultTranslations(v, global.Trans)}if err != nil {return err}// 注册自定义标签名函数, 用于获取结构体标签中的json字段名v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})return nil
}
2. 使用翻译后的错误信息

在处理请求时,捕获校验错误并翻译:

// removeTopStruct 移除字段名中的结构体名称
func removeTopStruct(fields map[string]string) map[string]string {res := map[string]string{}for field, err := range fields {res[field[strings.Index(field, ".")+1:]] = err}return res
}
func handleResponseValidateErr(c *gin.Context, err error) {// 断言错误类型if errs, ok := err.(validator.ValidationErrors); ok {c.JSON(http.StatusBadRequest, gin.H{"message": removeTopStruct(errs.Translate(global.Trans))})return}c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
}func Login(c *gin.Context) {var req LoginReqerr := c.ShouldBindJSON(&req)if err != nil {// c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})handleResponseValidateErr(c, err)return}c.JSON(http.StatusOK, gin.H{"message": "success","code":    0,"token":   "Abcd123456FGH",})
}

此时,错误信息将显示为中文,如 “Username 为必填字段” 或 “Password 长度必须至少为 6 个字符”。
在这里插入图片描述

四、自定义校验规则

虽然 validator 提供了丰富的内置规则,但在实际开发中,我们常需要自定义校验逻辑,如校验手机号、身份证、用户名格式等。

1. 定义自定义校验函数

以校验是否包含敏感词为例:


// 自定义验证函数
func validateSensitiveWord(fl validator.FieldLevel) bool {sensitiveWords := []string{"fuck", "shit", "fucking"}value := fl.Field().String()for _, word := range sensitiveWords {if strings.Contains(value, word) {return false}}return true
}
2. 注册自定义规则

在应用启动时,将自定义函数注册到 validator 引擎中:


func init() {if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//  注册自定义规则 sensitiveif err := v.RegisterValidation("sensitive", sensitiveWord); err != nil {return err}// 注册中文翻译if err := v.RegisterTranslation("sensitive", global.Trans,func(ut ut.Translator) error {return ut.Add("sensitive", "{0}包含敏感字符", true)},func(ut ut.Translator, fe validator.FieldError) string {t, _ := ut.T("sensitive", fe.Field())return t},); err != nil {return err}}
}
3. 在结构体中使用
type RegisterReq struct {UserName   string `json:"name" binding:"required,sensitive" label:"姓名"`Password string `json:"password" binding:"required,min=6,max=15" label:"密码"`
}

在这里插入图片描述

五、其他

  1. 多语言支持
    通过 universal-translator 可轻松支持多语言。根据请求头 Accept-Language 动态选择翻译器。

  2. 全局错误处理中间件
    将错误翻译逻辑封装为中间件,避免重复代码:

func ErrorHandler() gin.HandlerFunc {return func(c *gin.Context) {c.Next()if len(c.Errors) > 0 {err := c.Errors[0].Errif errs, ok := err.(validator.ValidationErrors); ok {var msgs []stringfor _, e := range errs {msgs = append(msgs, e.Translate(trans))}c.JSON(400, gin.H{"errors": msgs})return}c.JSON(400, gin.H{"error": err.Error()})}}
}
示例代码

gitee

http://www.xdnf.cn/news/18896.html

相关文章:

  • VS2022+QT6.7+Multimedia(捕获Windows音频数据,生成实时频谱)
  • 浅谈JMeter Listener
  • 安宝特方案丨AR异地专家远程支持平台,适合:机电运维、应急处置、监造验收
  • esp32c2 at 请问通过HTTPS进行OTA升级的AT命令流程有吗?
  • ERNIE 学习
  • Linux中Java后端调用外部进程 未处理后台输出流 导致io阻塞问题解决方法
  • Mac训练大模型:MLX-LM框架LoRA训练Qwen3并集成SwanLab进行可视化
  • VMware + Ubuntu 桥接模式不能联网 的常见原因、排查思路和解决步骤
  • leetcode 3446. 按对角线进行矩阵排序 中等
  • 与trae携手,构建owtb一体化物流平台之--需求文档V0.3
  • 第五章:Go运行时、内存管理与性能优化之Go垃圾回收机制 (GC) 深入
  • UDS NRC24
  • AI智能农业监测系统深度解读:从大田作物管理到病虫害预警,破解传统农业增产难题
  • 终极实战 - 全链路排查一次“502 Bad Gateway”
  • 从用户视角出发:如何提升B端产品的操作效率?
  • 【第四章】BS 架构测试全解析:从功能验证到问题定位​
  • 使用 logging 模块生成 .log 文件
  • SMU算法与人工智能创新实践班SMU2025 Summer 7th 参考题解
  • npm install 安装离线包的方法
  • 光谱相机在雾霾监测中有何优势?
  • ABeam中国 | 中国汽车市场(5)——软件定义汽车(SDV)的智能化应用场景
  • MATLAB中的蛙跳算法实现
  • Android Glide插件化开发实战:模块化加载与自定义扩展
  • 从0开始搭建一个前端项目(vue + vite + typescript)
  • AI驱动企业数字化转型:解码未来三年的智能化变革密码
  • 深度学习④【经典卷积神经网络演进:从LeNet到ResNet(重要意义)的架构革命】
  • 【目标检测】论文阅读6
  • nvme ,文件系统、namespace、LBA,文件名的浅浅理解
  • 解决Visual Studio中UWP设计器无法显示的问题:需升级至Windows 11 24H2
  • SynClub-百度在海外推出的AI社交产品