Revel表单验证需手动触发、显式保留、模板配合三者缺一不可;漏掉c.Validation.Keep()或c.FlashParams()错误将不显示,验证链须在参数接收后、业务逻辑前逐条调用,模板取值需严格匹配变量名并判空。

Revel 表单验证不是“加个标签就完事”,必须手动触发、显式保留、模板配合三者缺一不可;漏掉 c.Validation.Keep() 或 c.FlashParams(),错误就根本不会显示。
验证链必须写在参数接收之后、业务逻辑之前
Revel 不会自动扫描控制器方法里的变量并校验,所有 Validation 调用都得你亲手写,且顺序不能错。
- 先接收参数(如
func (c App) Submit(username string, email string)) - 紧接着逐条调用校验方法:
c.Validation.Required(username)、c.Validation.MinSize(username, 4)、c.Validation.Match(username, regexp.MustCompile("^\w*$")) - 每条失败都会以变量名(
username)为 key 存入.errors,模板里靠这个 key 取提示 - 不要把校验写在
if c.Validation.HasErrors()里面——它只判断结果,不执行校验
验证失败后必须三步连做:Keep → FlashParams → Redirect
Revel 的错误和参数默认是请求级临时的,重定向后就丢了。想让用户看到错误还保留刚填的内容,这三步一个都不能跳。
-
c.Validation.Keep():把.errors序列化进 Flash cookie,否则.errors.username在模板里永远为空 -
c.FlashParams():把当前请求参数(username、email等)存进 Flash,模板中才能用{{.flash.username}}回填 input -
return c.Redirect(Your.Action):必须重定向到渲染页,不能直接c.Render()—— 否则 Flash 数据不会刷新,下次再进页面还会残留旧值
模板里取错误必须判空,且字段名要和变量名严格一致
Revel 模板不帮你兜底,{{.errors.username.Message}} 前不加 {{if .errors.username}},页面会 panic;字段名拼错或大小写不对,就取不到任何提示。
- 安全写法:
{{if .errors.username}}<small class="text-danger">{{.errors.username.Message}}</small>{{end}} - 字段名是 Go 变量名,不是 HTML 的
name="user_name"—— 即使表单里写name="user_name",只要控制器参数叫username string,key 就是username - 如果想顶部统一展示所有错误,用
{{range .errors}}{{.Message}}{{end}},但注意这会丢失字段上下文,无法定位具体哪一栏错了
正则匹配容易 panic,Match 的 $ 符号必须省略
c.Validation.Match() 内部会对正则做截断处理,硬加 $ 结尾会导致运行时报 panic: runtime error: invalid memory address。
- 正确写法:
c.Validation.Match(username, regexp.MustCompile("^\w*"))(无$) - 错误写法:
c.Validation.Match(username, regexp.MustCompile("^\w*$"))(带$) - 正则必须用
regexp.MustCompile()预编译,传 *regexp.Regexp,不能传字符串或未编译对象 - 如果需要更精确控制(比如按 Unicode 字符数而非字节长度校验),别依赖
MinSize/MaxSize,改用自定义闭包校验
最常被忽略的是:Flash 模块必须启用,且目标 Action(比如 Hotels.Settings)里必须调用 c.Render() 才能解包 .errors 和 .flash。如果那个 Action 是纯 JSON 返回或跳转逻辑,错误照样不会出现。


















