用 validator 包做结构体字段校验最省心:通过结构体标签声明规则,支持嵌套、自定义函数和跨字段比较,性能好且需字段导出;应全局复用 validator 实例,统一处理错误映射、Content-Type 检查、大 payload 限制,并覆盖 Query 和 Path 参数校验。

用 validator 包做结构体字段校验最省心
Go 没有内置的输入验证机制,直接手写 if 判断既重复又易漏。社区主流做法是用 go-playground/validator 配合结构体标签,把规则声明式地写在字段上。
它支持嵌套、自定义函数、跨字段比较(如 eqfield),且性能好(编译期生成校验逻辑)。注意:必须为字段加上导出首字母(如 Name 而非 name),否则 validator 无法反射访问。
type UserForm struct {
Name string `json:"name" validate:"required,min=2,max=20"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"required,gt=0,lt=150"`
}
- 初始化一次全局
validator.Validate实例,别每次请求都新建 - HTTP 请求中用
json.Unmarshal解码后立即调用Validate.Struct() - 错误提示需手动映射到前端友好的字段名(
FieldError.Field()返回的是结构体字段名,不是 JSON key)
HTTP handler 中提前拦截空值和非法 Content-Type
很多验证失败其实根本不用走到结构体校验层——比如客户端发了空 body、错的 Content-Type: text/plain 却期望解析 JSON,或者用了不支持的 HTTP 方法。
这类问题应在中间件或 handler 开头就处理,避免后续浪费资源。
立即学习“go语言免费学习笔记(深入)”;
动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包
- 检查
r.Method是否在允许列表(如只接受POST) - 用
r.Header.Get("Content-Type")判断是否含application/json,不含则直接返回415 Unsupported Media Type - 读取
r.Body前先用http.MaxBytesReader限制大小,防止恶意大 payload
避免在 BindJSON 后再手动校验字段长度或格式
很多人习惯用 c.ShouldBindJSON(&v)(Gin)或 json.Unmarshal 后,再写一堆 if len(v.Name) ——这等于绕过了 validator 的统一能力,还容易遗漏边界情况(比如 Unicode 字符数 vs 字节数)。
validator 的 min=2 默认按符文(rune)计数,比 len() 更符合语义;email 校验也比正则更健壮(支持国际化域名)。
- 不要混合使用手动判断和
validator,选一个并贯彻到底 - 若需特殊逻辑(如“密码不能等于用户名”),用
RegisterValidation注册自定义规则,而不是在 handler 里 if-else - 注意
omitempty和required冲突:字段带omitempty且值为空时,validator可能跳过校验
Query 参数和 URL path 参数也要验证,别只盯 JSON body
API 不只收 JSON,还有 GET /users?id=123&role=admin 这类查询参数,或 DELETE /users/:id 中的路径参数。它们同样可能被篡改、为空、类型错误。
Gin 用户可用 c.ShouldBindQuery(&v) 或 c.Param("id") 后转成整型再校验;原生 net/http 则需手动取 r.URL.Query().Get("id") 并解析。
- 路径参数(如
:id)建议统一用strconv.ParseInt或uuid.Parse,失败即返回400 Bad Request - Query 参数若对应结构体,一样可打
validate标签,再用validator校验 - 别假设
id是数字就直接传给数据库——SQL 注入风险仍在,应始终走参数化查询
if err != nil 更可持续。









