Gin 默认不校验参数,因Bind类方法仅映射数据而不触发字段校验,需显式添加binding标签并用ShouldBind调用validator;结构体字段须标注如required、email等规则,嵌套结构需dive,错误需断言ValidationErrors提取字段信息统一处理。

为什么 Gin 默认不校验参数?
Gin 本身只做路由和上下文管理,Bind 类方法(如 BindJSON、ShouldBind)只是把请求数据映射到结构体,**不会自动触发字段级校验**。你得显式启用校验机制,否则空字符串、负数 ID、超长邮箱都会被照单全收。
常见错误现象:接口返回 200,但数据库写入失败;前端传了非法邮箱,后端没拦住,发信模块崩溃。
- 必须给结构体字段加
binding标签,比如json:"name" binding:"required,min=2,max=20" - 用
ShouldBind替代Bind—— 前者会返回 error,后者静默失败 - 别依赖
BindJSON自动校验,它只解析,不校验(除非你手动调Validate)
怎么写一个带校验的请求结构体?
校验规则写在 struct tag 里,Gin 底层用的是 go-playground/validator v10+,语法和文档保持一致。注意大小写、引号、逗号分隔。
type CreateUserRequest struct {
Name string `json:"name" binding:"required,min=2,max=20"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"required,gt=0,lt=150"`
Password string `json:"password" binding:"required,min=8"`
}
-
required检查零值(空字符串、0、nil),不是检查是否存在字段 -
email只校验格式,不发验证邮件;url、uuid同理 -
gt/lt对 int/float 有效,min/max对 string/lenable 类型有效 - 如果字段可为空但有格式要求,用
omitempty,email,但注意:空字符串会跳过email校验
如何统一处理校验失败?
每次手写 if err != nil { c.JSON(400, ...) } 很重复。推荐中间件或封装函数,但别直接改 Gin 的 c.Error() —— 它只存 error,不响应。
立即学习“go语言免费学习笔记(深入)”;
- 用
c.ShouldBind(&req),不是c.Bind(&req) - 错误类型是
validator.ValidationErrors,可断言后提取字段名和实际错误信息 - 别用
err.Error()直接返回 —— 中文提示不可读,且含结构体路径(如createuserrequest.Email) - 示例提取方式:
if err := c.ShouldBind(&req); err != nil { if errs, ok := err.(validator.ValidationErrors); ok { for _, e := range errs { // e.Field() → "Email", e.Tag() → "email", e.Param() → "" } } }
嵌套结构体和数组怎么校验?
嵌套 struct 自动递归校验,但需确保子 struct 字段也有 binding 标签;数组/切片元素校验要加 dive。
type OrderRequest struct {
Items []struct {
ID int `json:"id" binding:"required,gt=0"`
Count int `json:"count" binding:"required,gte=1,lte=999"`
Sku string `json:"sku" binding:"required,min=3,max=32"`
} `json:"items" binding:"required,dive"` // ← 必须加 dive
}
- 没有
dive,items切片本身只校验是否非 nil,不校验每个元素 -
dive不支持 map value 校验,map 要转成 struct 或自定义校验器 - 嵌套 struct 内部字段若没加
binding,默认跳过,不会报错 - 性能影响:深度嵌套 + 大量字段时,校验开销明显,高并发场景建议预编译 validator 实例(
validator.New())
真正麻烦的不是写标签,而是错误提示对齐业务语义 —— 比如 “手机号格式错误” 不能只靠 phone tag,得自己注册自定义校验函数并翻译。这点容易被忽略,一上线就被产品追问“为什么报英文”。


















