revel模板中必须通过拦截器统一注入resourceversion,不可在各action中手动赋值,否则易遗漏、难维护、违背配置即版本原则;需在init.go注册拦截器并确保位于revel.harness.init()之前,且app.conf中正确定义resourceversion。

Revel 模板中显示版本号,本质是把一个字符串变量从控制器注入到模板上下文,再用 {{.resourceVersion}} 输出——但必须走拦截器统一注入,不能在每个 Action 里手动塞值,否则维护成本高、容易漏。
为什么不能直接在 Controller 里用 c.RenderArgs["version"] = "1.2.3"
可以临时这么做,但很快会失控:每次加新页面、改路由、写新 Action 都得重复一遍;如果某次忘记传,模板里 {{.version}} 就静默为空,前端看不到任何提示;更麻烦的是,版本号通常来自配置或构建环境,硬编码在代码里违背“配置即版本”原则。
- 拦截器方式只需注册一次,所有请求自动带
resourceVersion - 若改用 Git commit SHA,只需改
app.conf一行,无需动 Go 代码 - 不启用拦截器时,
{{.resourceVersion}}在模板中永远求值为<nil></nil>,且不报错
必须注册拦截器并在 init.go 中启用
在 app/controllers/resourceversion.go 定义函数后,一定要在 app/init.go 的 init() 函数里注册它,且位置要在 revel.Harness.Init() 之前:
revel.InterceptMethod(controllers.SetVersion, revel.BEFORE)
常见错误是把它写在 revel.Harness.Init() 之后,结果拦截器完全不生效,.resourceVersion 始终为空。另外,确保 app.conf 里已定义:
resourceVersion = ${GIT_COMMIT:1}
这样即使环境没设 GIT_COMMIT,也会 fallback 到默认值 "1"。
模板中安全拼接静态资源 URL
版本号最常用场景是给 CSS/JS 加 ?v= 参数。直接写 /public/js/app.js?v={{.resourceVersion}} 有风险:如果 .resourceVersion 是空字符串或含特殊字符(如 /、&),URL 会出错。
- 推荐写法:
/public/js/app.js?v={{.resourceVersion | urlquery}},urlquery是 Go 模板内置函数,自动做 URL 编码 - 不要用
{{.resourceVersion | safe}}——safe不是 Revel 默认注册的函数,会报function "safe" not defined - 若需更复杂逻辑(如只对 prod 环境加版本号),应提前在拦截器里计算好,传入
c.RenderArgs["staticVersion"],模板只负责输出
验证是否生效的最快方法
别等部署后再查,本地就能确认:
- 在任意模板顶部加一行:
{{print "DEBUG VERSION:" .resourceVersion}},刷新页面看终端日志是否输出对应值 - 打开浏览器开发者工具 → Network 标签页,点一个 JS 文件,看 Request URL 是否含
?v=abc1234 - 故意把
app.conf中的resourceVersion改成test-{{now}},再刷新——如果 URL 里出现test-%!s(MISSING),说明模板函数调用失败,now未注册
最容易被忽略的是:拦截器注册后必须重启 revel run,热重载不会加载新注册的拦截器。











