shouldbindjson能触发校验,但必须显式添加binding标签(如binding:"required"),否则零配置即零校验;字段需配json tag、传指针、类型匹配,且tag内逗号不可有空格。

直接用 c.ShouldBindJSON 就能触发校验,但不加 binding 标签或写错 tag,它就完全不校验——不是“默认校验”,而是“零配置即零校验”。
binding 标签没生效?先确认这三件事
常见错误现象:结构体字段为空、缺失或为零值,c.ShouldBindJSON 却返回 nil,后续业务逻辑直接用零值跑飞。
-
binding标签必须显式写,比如binding:"required";只写json:"name"不会触发任何校验 - 字段类型要匹配:比如想校验
"age": 0是否合法,不能用*int+required(nil 指针会被跳过),得用int+required,gte=0 - 标签值里逗号不能有空格:
binding:"required, min=6"是错的,必须写成binding:"required,min=6"
JSON / Query / Form 参数校验,tag 和绑定方法要配对
同一个结构体不能靠一套 tag 通吃所有输入源——binding 标签只是规则声明,真正解析时依赖字段上的 json、form 或 uri 标签来定位数据来源。
- 接收 JSON Body:字段用
json:"xxx",绑定调c.ShouldBindJSON(&v) - 接收 URL Query(如
/search?k=go&page=1):字段用form:"k",绑定调c.ShouldBindQuery(&v),tag 写binding:"required,gt=0" - 接收 multipart/form-data:字段用
form:"file",绑定调c.ShouldBind(&v)(自动识别格式),binding规则照常生效
嵌套结构体、切片、跨字段比较怎么写 tag
validator 默认不递归校验嵌套字段,也不检查 slice 元素,更不会自动比对两个字段是否相等——这些都得靠特定 tag 显式打开。
- 嵌套结构体要校验:在字段 tag 加
dive,例如Address Address `json:"address" binding:"dive"` - 切片元素逐个校验:同样用
dive,例如Items []Item `json:"items" binding:"dive" - 两个字段值必须一致:用
eqfield=OtherField,注意是字段名(非 JSON key),且目标字段必须在同一级结构体中,例如RePassword string `json:"re_password" binding:"eqfield=Password"` - 字段必须出现在请求中(哪怕值为零):用
exists,例如Age int `json:"age" binding:"exists,gte=0"`,可捕获{"name":"a"}缺少age的情况
错误提示中文化和自定义规则容易卡在哪
默认错误信息是英文、带字段路径(如 Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag),直接返回给前端既不友好也不安全。
- 中文翻译必须注册翻译器:Gin 自带
binding.Validator.Engine()返回的是*validator.Validate实例,需手动调RegisterTranslation并绑定Translations函数 - 自定义规则(如手机号、身份证)要用
RegisterValidation,且函数签名必须是func(fl validator.FieldLevel) bool,返回true表示通过 - 结构体级别校验(比如“姓名和昵称不能同时为空”)得用
RegisterStructValidation,且必须在路由注册前完成,否则运行时无效
最常被忽略的一点:校验失败后,err 是 validator.ValidationErrors 类型,直接 err.Error() 会暴露字段名和内部结构。对外 API 应统一提取第一个错误或遍历转成 map[string]string,而不是原样透出。











