Go数据校验应使用validator库,需为struct字段添加validate标签(如required、email)、传指针调用Validate.Struct()、嵌套结构体加embedded标签、指针类型注意nil判断,自定义验证需提前注册函数。

Go 里做数据校验,别直接手写 if 堆砌逻辑——用 validator 库是主流且可靠的选择,但必须手动注册结构体标签、注意嵌套字段和指针零值行为,否则校验会静默失效。
怎么给 struct 字段加校验规则(validator 标签写法)
校验靠结构体字段的 validate tag 控制,不是函数调用也不是注释。常见规则直接写在双引号里,多个用逗号分隔。
-
required表示非空(对 string 是非空字符串,对 int 是非零,对指针是不为 nil) -
email自动验证邮箱格式,但不发请求确认 -
min=1,max=100适用于数字和字符串长度(len=6更明确) -
omitempty不是校验规则,而是告诉validator:该字段为空时跳过校验(常和required互斥) - 自定义错误消息要额外传
error参数,不能写在 tag 里
示例:
type User 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"`
}
为什么 Validate.Struct() 返回 nil 却没生效
最常见原因是传入了值而非指针。校验器内部需要取地址来读取 struct tag,如果传 User{} 这样的值类型,反射无法获取其字段 tag,导致跳过所有校验且不报错。
- 必须传指针:
validate.Struct(&user),而不是validate.Struct(user) - 嵌套结构体字段也要加
validatetag,否则只校验顶层 - 字段是
*string或*int等指针类型时,required检查的是指针是否为 nil,不是解引用后的值 - 如果字段是匿名嵌入(如
BaseModel),需加embeddedtag 才能递归校验
如何处理 JSON 解析后校验失败的字段(UnmarshalJSON + Validate 配合)
先解析再校验是标准流程,但要注意错误合并和字段定位。不要在 Unmarshal 失败后还调用 Validate,因为结构体可能处于未定义状态。
- 先用
json.Unmarshal解析,检查 error;若失败,直接返回解析错误,别继续校验 - 解析成功后,立刻调用
validate.Struct(),并用ValidationErrors类型断言获取具体字段和原因 - 避免用
fmt.Sprintf("%v", err)输出校验错误——它不带字段名;要用err.(validator.ValidationErrors)遍历每个FieldError - 时间字段如
time.Time默认不支持datetime校验,需配合time.Parse预处理或用自定义验证函数
自定义验证函数怎么注册(RegisterValidation 实操)
内置规则不够用时,比如校验手机号、身份证号、密码强度,就得注册自己的函数。关键点是函数签名必须匹配,且注册要在校验前完成(通常放 init() 或服务启动时)。
- 函数签名固定为:
func(fl validator.FieldLevel) bool - 用
validate.RegisterValidation("chinese_mobile", mobileValidator)注册,之后就能在 tag 写chinese_mobile -
fl.Field().Interface()获取当前字段值,注意类型断言安全(比如先判断是否为string) - 注册一次即可,重复注册会 panic;建议用单例 validator 实例(
validator.New())管理 - 正则类校验慎用
regexp.MustCompile在函数内——应提前编译好,避免每次调用都重编译
真正麻烦的不是写校验逻辑,而是字段为 nil 指针时 required 的语义差异,以及嵌套结构体忘记加 embedded 导致深层字段完全不参与校验——这两个点线上出问题最多,调试时容易忽略。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











