validate标签覆盖90%校验需求,但标签语法错误、omitempty位置不当、指针/零值误判及字段未导出导致eqfield失效,是验证静默跳过的主因。

直接用 validate 标签能覆盖 90% 的字段校验需求,但标签写错、忽略初始化或误读 omitempty 行为,是导致验证“看似生效实则跳过”的最常见原因。
validate 标签语法和分隔符必须严格按规则写
标签值不是自由字符串,逗号,、竖线|、横线- 都有明确语义,且**中间不能有空格**。写成 required, min=2(带空格)会导致 min=2 被整个忽略。
-
required,min=2,max=20:从左到右执行,required失败就不再检查长度 -
email|url:满足任一即可,注意是竖线|,不是or或英文逗号 -
-:整字段跳过校验,等价于没加标签,不是 “空值允许” - 多个 tag 键(如
json:"name" validate:"required")之间用空格分隔,但每个键内部的 value 里不能有多余空格
required 对指针和零值字段的行为容易误判
required 判定逻辑是 “非零值”,不是 “非空字符串” 或 “非 nil”。对 *string、*int 类型,它只检查指针是否为 nil;对 string、int 等值类型,则检查是否为 "" 或 0。
- 若字段是
Name *string,传入nil→required失败;传入new(string)但值为""→ 仍通过required(因指针非 nil),需额外加min=1 - 若字段是
Age int,传0→required失败,此时应改用gte=1或改字段为*int - 嵌套结构体字段默认自动深度校验,无需
dive;但切片/映射里的元素必须显式加dive,否则只校验容器本身长度
omitempty 不是“可选”,而是“零值时跳过后续规则”
omitempty 必须放在规则链**最左侧**才有效,且只影响它右边的规则。它不改变 required 的判定时机——required 仍会先执行并报错。
-
omitempty,required:无效,required仍会校验,omitempty无作用 -
omitempty,min=3:当字段为零值(如""或0)时,跳过min=3;但若字段非零,min=3正常执行 - 想表达“该字段可为空,但若填了就得符合规则”,正确写法是去掉
required,仅用min=3或email等条件规则
跨字段比较类标签(如 eqfield)依赖结构体字段名而非 JSON key
eqfield、gtfield 等规则比较的是同一结构体内**Go 字段名**,不是 json 或 form tag 的值。字段名大小写敏感,且必须导出(首字母大写)。
-
ConfirmPassword string `validate:"eqfield=Password"`:正确,比较Password字段值 -
confirm_password string `validate:"eqfield=Password"`:错误,小写字段无法被反射读取,eqfield查不到目标字段,静默失效 -
Password string `json:"password"`和ConfirmPassword string `json:"confirm_password"`:不影响eqfield,它只认Password和ConfirmPassword这两个 Go 名 - 若需比较不同结构体字段,得手动在
Validate()方法里实现,eqfield不支持跨 struct
真正难调试的永远不是“规则写不出来”,而是规则写了但被 omitempty 截断、被指针零值绕过、或因字段未导出而被 eqfield 忽略——这些都不会报错,只会让验证逻辑静默失效。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











