shouldbind默认不触发validate标签,因fiber仅解析binding标签;需提前设置app.validator为自定义structvalidator实例,并在validatestruct中用fe.field()获取json字段名、返回validator.validationerrors。

直接用 validator/v10 手动校验,别指望 c.ShouldBind() 自动触发自定义规则——Fiber 默认压根不读 validate 标签,除非你显式替换校验器实例。
为什么 c.ShouldBind() 不走 validate 标签
Fiber 的 c.ShouldBind() 默认只认 binding 标签(如 binding:"required,email"),它和 validate 标签完全无关。即使结构体同时写了 json 和 validate,只要没动 app.Validator 字段,validate 就是摆设。
- 默认行为:
c.ShouldBind()底层调用的是binding.DefaultValidator,它只解析bindingtag - 想用
validate,必须提前设置:app.Validator = &customValidator{} - 这个赋值必须在注册任何路由前完成,否则中间件已初始化,改了也无效
如何实现 binding.StructValidator 接口
核心是写一个满足 binding.StructValidator 接口的类型,重点在 ValidateStruct 方法里组合原校验器 + 业务逻辑。
- 字段名要用
fe.Field()(对应 JSON key),不是fe.StructField()(对应 Go 字段名) - 错误必须包装成
validator.FieldError,否则c.Errs()拿不到 - 推荐复用官方
validator.New()实例做基础校验,再追加自定义检查(比如密码 vs 用户名比对) - 别在
ValidateStruct里 panic 或 return nil 错误——空 error 表示校验通过,要返回validator.ValidationErrors才算“有错”
嵌套结构体里 eqfield 失效怎么办
validate:"eqfield=Password" 在嵌套 struct 中失效,是因为 eqfield 默认只查当前层级字段,不会向上穿透到父 struct。
- 例如
User.Profile.Password和User.ConfirmPassword,eqfield=Password会去Profile里找Password,而不是去User层找 - 解决办法:把需要比对的字段拉平到同一级,或改用自定义函数(
v.RegisterValidation("sameas", sameAsFunc)) - 自定义函数里可用反射取
struct的任意嵌套字段,控制权完全在你手上 - 注意:自定义函数接收的是
interface{},需手动断言类型,避免 panic
required 为什么拦不住空格字符串
required 对 string 类型只判断是否为 "",对 " "、"\t\n" 完全放行。
- 高频翻车点:前端提交带空格的邮箱/用户名,后端
required过了,但业务逻辑炸了 - 安全做法是组合
min=1:validate:"required,min=1"(注意:min=1前不能有空格) - 更彻底方案:注册
notblank自定义规则,内部先strings.TrimSpace()再判空 - 别依赖
omitempty——它只影响 JSON 解码时是否跳过字段,和校验零关系
真正麻烦的不是写校验逻辑,而是字段名映射和错误归一化:前端按 JSON key 消费错误,但 validator 默认返回的是 struct 字段名;同一个字段在不同接口可能要返回不同中文提示,得靠 fe.Field() 查表,漏一条就导致前端展示异常。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











