Beego validation包不支持全局自定义验证函数,须通过StructTag(仅内置规则如Required/Match)或Valid方法(实现ValidFormer接口)实现;字段联动、复杂逻辑及错误提示统一管理必须在Valid方法中手动处理。

Beego 的 validation 包不支持直接注册全局自定义验证函数,必须通过 StructTag 或手动调用验证器方法实现;硬塞进 tag 的正则或逻辑一旦复杂就难调试,别图省事写一堆嵌套括号。
StructTag 里怎么写自定义校验逻辑
StructTag 本身不执行任意 Go 代码,所谓“自定义”只能是 validation 内置函数的组合(如 Required、Match、Range),或靠 Valid 方法兜底。常见误区是以为能在 tag 里写 CustomCheck 这种函数——它根本不存在。
- 合法写法示例:
`valid:"Required; Match(/^1[3-9]\d{9}$/); Mobile"`—— 多个内置规则用分号拼接,Mobile是内置手机号校验 - 非法写法:
`valid:"CustomCheck"`—— 运行时会静默忽略,不会报错,但也不起效 - 真正需要自定义逻辑(比如“用户名不能含 admin 且不能全数字”)必须实现在
Valid方法里,且结构体指针需实现validation.ValidFormer接口
在 Valid 方法里做字段间联动校验
当验证依赖多个字段(如“密码”和“确认密码”是否一致、“开始时间”不能晚于“结束时间”),StructTag 无能为力,必须进 Valid 方法手动处理。
-
Valid方法签名固定为func (u *YourStruct) Valid(v *validation.Validation),参数v是验证上下文 - 用
v.SetError("FieldName", "错误提示")主动注入错误,HasErrors()才会返回true - 注意:字段名必须和 struct 字段名完全一致(大小写敏感),否则前端取不到对应错误信息
- 示例中常见漏掉
strings.TrimSpace导致空格干扰比对,建议在Valid开头统一清洗输入
手动调用 validation.Validation 实例的坑
绕过 StructTag、直接在 Controller 里 new 一个 validation.Validation 并链式调用(如 valid.Required(...).MaxSize(...)),看似灵活,但容易踩三个隐性坑:
- 每个验证方法返回的是
*validation.Result,不是原Validation实例,链式调用后若没检查.Ok就继续下一条,错误会丢失 - 错误 key 默认是传入的字符串(如
"name"),但 Controller 渲染模板时通常按字段名取值(如{{.VerifyName}}),key 对不上就显示不出错误 -
MaxSize、Range等函数对非字符串/数字类型(如 nil 指针、空切片)行为未明确定义,可能 panic,务必先判空
前端模板里怎么正确显示字段级错误
Beego 不自动把验证错误映射到模板变量,必须在 Controller 里显式赋值,比如 c.Data["VerifyName"] = "用户名不能为空"。StructTag 验证失败后,valid.Errors 是个 slice,得自己遍历提取。
- 推荐做法:遍历
valid.Errors,用err.Key作为 map key,构建map[string]string后整体塞进c.Data - 不要依赖
{{.VerifyName}}自动渲染 —— 它只是个字符串,Beego 不做任何 magic 绑定 - 如果用了
Valid方法,错误 key 必须和 struct 字段名一致,否则你塞进去的"Name"和模板里写的{{.VerifyName}}根本不匹配
最麻烦的其实是错误文案的维护:StructTag 里的 Message 只能用于单条规则,Valid 方法里却要手拼中文,一改字段名就得同步改所有地方。真要长期维护,建议把错误提示抽成常量 map,按字段+规则类型索引。


















