validator.validate 返回的是 validator.validationerrors 类型,需类型断言后遍历获取字段名和验证标签;required 对 nil 指针无效,应改用 required_with 或 nonzero;嵌套结构体错误应使用 structnamespace() 获取完整路径;自定义验证函数需自行 recover panic 并返回明确错误。

validator 包的 Validate 方法返回的错误不是 error 而是 validationErrors
调用 Validate 后直接用 fmt.Println(err) 或 log.Printf("%v", err),看到的是一串无法直接读取字段和原因的结构体输出,比如 Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag —— 这其实是 validator.ValidationErrors 类型,它实现了 error 接口,但内部是切片,不能当普通字符串错误处理。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 必须用类型断言转成
validator.ValidationErrors才能遍历每个字段错误 - 不要用
errors.Is或errors.As判断验证失败,它们对ValidationErrors无效(这是个切片,不是单个 error) - 常见写法是:
if errs, ok := err.(validator.ValidationErrors); ok { for _, e := range errs { log.Printf("field %s failed on tag %s", e.Field(), e.Tag()) } }
struct tag 中 validate 的值写错导致静默跳过验证
比如写成 validate:"required,email" 看似没问题,但若 struct 字段是 *string 类型且值为 nil,required 不会触发 —— 因为 required 只对非 nil 零值生效;真正该用的是 required_if 或更明确的 notblank(需启用 SetTagName 并注册),或者改用 nonzero(针对指针)。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
-
required对*string、*int等指针类型无效(nil 时直接跳过),要用required_with或自定义函数 - 邮箱验证推荐用
email,但注意它不校验 DNS 或 MX 记录,只是正则匹配,别误以为能防伪造邮箱 - 如果用了
omitempty,又希望空字符串也被验证,得去掉omitempty或显式赋空字符串,否则字段被忽略
嵌套 struct 验证失败时,Field() 返回的是全路径名,不是字段名
比如 User.Profile.Address.Street 验证失败,e.Field() 返回的是 Street,但 e.StructNamespace() 才是完整路径。很多人只看 Field() 就以为字段名就是 Street,结果前端映射报错位置时找不到对应 key。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 需要精确返回前端字段路径时,优先用
e.StructNamespace()(如User.Profile.Address.Street) -
e.StructField()返回的是结构体中定义的字段名(如Street),适合日志记录,不适合做 UI 映射 - 如果用了匿名嵌套(如
Profile struct{ Address }),StructNamespace()会展开,但Field()仍只返回最内层字段名,容易混淆
validator 注册自定义函数后,panic 报错提示里不显示函数名
比如注册了 registerCustomFunc("phone", phoneValidator),但验证失败时 panic 信息只说 failed on the 'phone' tag,并不告诉你具体哪行代码抛了 panic —— 因为 validator 内部用 reflect 调用,堆栈被截断。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 所有自定义验证函数必须自己 recover panic,并转成明确错误(比如
return false, fmt.Errorf("invalid phone format: %v", v)) - 别在自定义函数里直接调用
log.Fatal或os.Exit,会导致整个服务退出 - 调试时可临时加
defer func(){ if r := recover(); r != nil { log.Printf("panic in phone validator: %+v", r) } }()










