go-validator 本身不拦截请求,需通过中间件或显式调用 validate.struct() 触发校验;gin 的 shouldbind 自动集成 validator 并返回 400,而 net/http 需手动解码、校验及响应。

Go-validator 不能直接拦截请求,得靠中间件或结构体绑定时触发
Go-validator(比如 go-playground/validator/v10)本身不提供 HTTP 拦截能力,它只是校验结构体字段的工具。真正“拦截异常请求”的动作,必须由你主动调用 Validate.Struct() 并配合 HTTP handler 的错误返回逻辑来完成。
常见误区是以为加个 tag 就自动拒绝非法请求——不会。没手动校验、没写 if err != nil 返回 400,再严格的 validate:"required,email" 也形同虚设。
- 校验必须显式调用
validate.Struct()或validate.Var() - HTTP handler 中需检查校验错误,并返回
http.StatusBadRequest - 别把 validator 当成 Gin 的
ShouldBind那种自动校验——Gin 是封装了 validator,原生 net/http 不会帮你做
在 Gin 中用 ShouldBind + validator tag 最省事
Gin 内置的 ShouldBind() 默认就用了 go-playground/validator,只要结构体字段打上 tag,就能自动校验并返回 400 错误。这是最接近“拦截”效果的做法。
示例:
type CreateUserReq struct {
Name string `json:"name" validate:"required,min=2,max=20"`
Email string `json:"email" validate:"required,email"`
}
func CreateUser(c *gin.Context) {
var req CreateUserReq
if err := c.ShouldBind(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 正常处理...
}
-
ShouldBind会自动调用 validator,且对 JSON、form-data、URL query 都兼容 - 错误信息默认较简略(如
"Key: 'CreateUserReq.Email' Error:Field validation for 'Email' failed on the 'email' tag"),如需友好提示,得自己解析validator.ValidationErrors - 注意:Gin v1.9+ 默认使用 validator v10;旧版可能用 v9,tag 语法略有差异(比如 v9 不支持
email,得用isemail)
在 net/http 中手动校验要自己搭“拦截”逻辑
不用框架时,没有 ShouldBind,你得自己解码 JSON、手动调用 validator、手动写错误响应——这才是真正暴露 validator 原始用法的地方。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
关键步骤缺一不可:
- 先用
json.Decode()解析到结构体 - 再用
validate.Struct()校验 - 检查错误类型是否为
validator.ValidationErrors,以便区分业务错误和校验失败 - 别忘了设置响应头
Content-Type: application/json
片段示例:
v := validator.New()
var req CreateUserReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
if err := v.Struct(req); err != nil {
if _, ok := err.(validator.ValidationErrors); ok {
http.Error(w, "validation failed", http.StatusBadRequest)
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
自定义错误提示和多语言支持容易被忽略
默认错误信息对前端不友好,也不支持中文。想返回类似 {"field": "email", "message": "邮箱格式不正确"},必须手动遍历 validator.ValidationErrors 并映射。
要点:
- 断言错误为
validator.ValidationErrors后,可用err.Translate(trans)配合翻译器实现多语言(需提前注册trans.RegisterTranslation) - 更轻量做法是遍历
err的每个FieldError,按error.Field()和error.Tag()查 map 映射中文提示 - 别在每次请求都新建
validator.New()——复用全局单例,否则有性能损耗 - 嵌套结构体校验默认开启,但若字段是
*string且为 nil,required不会触发(需改用required_if或自定义函数)
复杂点在于:错误映射逻辑一旦散落在多个 handler 里,就难维护;建议抽成统一的 BindAndValidate(w, r, &req) 工具函数,把解码、校验、错误响应全包进去。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










