From d549cf929bcd2f5dadc665976d02447cba1f7908 Mon Sep 17 00:00:00 2001 From: black1552 Date: Tue, 3 Feb 2026 17:09:46 +0800 Subject: [PATCH] =?UTF-8?q?refactor(valid):=20=E9=87=8D=E6=9E=84=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E5=88=9D=E5=A7=8B=E5=8C=96=E5=92=8C=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整全局变量声明顺序并移除未使用的 uni 变量 - 添加 ApiResponse 结构体定义 - 重命名 GetFirstValidateError 函数为 ValidateError - 优化 init 函数中的中文本地化初始化流程 - 更新字段名映射函数的注释说明 - 改进错误处理逻辑和代码注释 --- valid/valid.go | 54 +++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/valid/valid.go b/valid/valid.go index b3a68f8..c2bcd68 100644 --- a/valid/valid.go +++ b/valid/valid.go @@ -11,60 +11,64 @@ import ( zh_translations "github.com/go-playground/validator/v10/translations/zh" ) +// -------------------------- 全局变量(翻译器+验证器) -------------------------- var ( - uni *ut.UniversalTranslator // 全局翻译器实例 - validate *validator.Validate // 全局验证器实例 - trans ut.Translator // 全局中文翻译器 - foun bool + trans ut.Translator // 全局中文翻译器 + validate *validator.Validate // 全局验证器实例 + found bool ) +// -------------------------- 统一响应格式 -------------------------- +type ApiResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data interface{} `json:"data"` +} + +// -------------------------- 初始化全局验证器+中文翻译器(关键:与Gin关联) -------------------------- func init() { - // 1. 初始化中文本地化实例 + // 1. 初始化中文本地化 zhLocale := zh.New() + uni := ut.New(zhLocale, zhLocale) - // 2. 初始化通用翻译器,加载中文本地化 - uni = ut.New(zhLocale, zhLocale) - - // 3. 获取中文翻译器实例 + // 2. 获取中文翻译器 var err error - trans, foun = uni.GetTranslator("zh") - if !foun { + trans, found = uni.GetTranslator("zh") + if !found { panic("获取中文翻译器失败") } - // 4. 获取 Gin 内置的 validator 验证器实例 + // 3. 关键:获取 Gin 内置的 validator 实例(而非手动创建 new(validator.Validate)) + // 保证 Gin 绑定参数时使用的是我们注册了翻译的这个验证器 validate = validator.New() - // 5. 注册 validator 中文翻译(替换默认英文错误提示) + // 4. 注册中文翻译(核心:将验证器与中文翻译器绑定) err = zh_translations.RegisterDefaultTranslations(validate, trans) if err != nil { panic("注册中文翻译失败:" + err.Error()) } - // 6. 核心优化:注册字段名映射函数,用结构体的 json 标签作为返回的字段名 - // 例如:结构体字段 Username -> json 标签 username -> 错误提示中显示 username(更友好) + // 5. 注册字段名映射:用 json 标签替换结构体字段名(解决报错中的 Title -> title 问题) validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - // 提取 json 标签(忽略 ,omitempty 等附加选项) + // 提取 json 标签,忽略 ,omitempty 等附加选项 jsonTag := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - // 若 json 标签为 "-"(表示忽略该字段),返回空字符串 if jsonTag == "-" { return "" } return jsonTag }) } -func GetFirstValidateError(err error) string { - // 1. 断言错误类型是否为 validator 验证错误 + +// ValidateError -------------------------- 工具函数:解析第一条验证错误(中文翻译) -------------------------- +func ValidateError(err error) string { + // 1. 断言错误类型为 validator.ValidationErrors var validateErrors validator.ValidationErrors ok := errors.As(err, &validateErrors) if !ok { - // 非参数验证错误(如绑定格式错误),直接返回错误信息 + // 非参数验证错误,直接返回 return "参数格式错误:" + err.Error() } - // 2. 仅返回第一条验证错误(核心:取切片索引 0 的元素) - firstErr := validateErrors[0] - - // 3. 翻译第一条错误为中文,返回给前端 - return firstErr.Translate(trans) + // 2. 只返回第一条中文翻译错误 + return validateErrors[0].Translate(trans) }