Revel 模板渲染依赖约定路径 app/views/Controller/Action.html,大小写敏感;Render 传参自动生成小驼峰变量名,RenderTemplate 需手动设 RenderArgs;range 遍历需双变量传索引;layout 中 {{yield}} 插入 action 内容,{{include}} 复用组件,不可混用。

Revel 框架的模板渲染不是靠“设置模板路径”这种手动配置完成的,而是由约定目录结构 + RenderTemplate 或 Render 自动驱动的。只要目录对、命名对、数据传对,页面就出来;配错一个环节,就会 404 或空数据。
模板文件必须放在 app/views/ 下且遵循命名约定
Revel 不读取任意路径的 HTML 文件。它只认 app/views/ 这种结构:
- 控制器名首字母大写,如
App→ 对应目录app/views/App/ - Action 方法名(如
Index)→ 模板文件名必须是Index.html - 若调用
c.RenderTemplate("App/Show.html"),则实际查找路径是app/views/App/Show.html,不是相对当前模板位置 - 错误现象:404 报错里明确写
template "App/Index.html" not found,大概率是大小写或目录层级错了
Render 和 RenderTemplate 的参数传递差异
二者都触发模板渲染,但数据注入方式不同:
-
c.Render(username, email)→ 模板中直接用.username、.email访问,变量名自动转为小驼峰(UserName→.userName) -
c.RenderArgs["user"] = user+c.RenderTemplate("User/Show.html")→ 模板中用.user.Name,.user是你手动塞进RenderArgs的 key - 混用风险:如果同时调用
c.Render(u)又设c.RenderArgs["u"] = u,后者会覆盖前者——因为Render内部也是往RenderArgs里写 - 常见坑:
c.Render(user)后在模板里写.User.Name会 panic,正确是.user.Name(小写开头)
动态内容必须显式解构 range 才能拿到索引
遍历切片时,{{range .Items}} 中的 . 是当前元素,**索引不会自动存在**。想传索引给子模板,必须用双变量语法:
- 错误写法:
{{range .Items}}{{template "item.html" .}}{{end}}→ 子模板收不到索引 - 正确写法:
{{range $i, $item := .Items}}{{template "item.html" (dict "Index" $i "Item" $item)}}{{end}} - 注意:
$i前的$不能省,否则在嵌套{{with}}或子模板里可能被同名字段覆盖 - 若没注册
dict函数(Revel 默认未注册),改用 map:{{template "item.html" (map "index" $i "value" $item)}},前提是已用revel.TemplateFuncs["map"] = func(...)注册过
layout 模板里 {{yield}} 和 {{include}} 别混用
这是最常导致“内容不显示”或“重复渲染”的地方:
-
{{yield}}只能在 layout 模板(如app/views/layouts/main.html)里用,它代表“此处插入当前 action 模板的主体内容” -
{{include "header.html" .}}是立即加载并渲染指定模板,.是当前上下文,可用于复用组件(如导航栏),但它和{{yield}}完全无关 - 典型错误:在
main.html里写了{{include "Index.html" .}}—— 这会把Index.html当作普通子模板渲染一次,但{{yield}}还会再插一遍,结果内容出现两次 - 正确组合:
main.html包含{{include "header.html" .}}+{{yield}}+{{include "footer.html" .}}
真正容易被忽略的是:Revel 的模板系统完全基于 Go 标准库 html/template,所有语法限制(比如不能在模板里调用方法、不能做算术、变量作用域严格受限)它都继承下来。别指望写个 {{.Items[0].Name}} 就能安全取值——如果 .Items 是 nil,整个页面直接 500;得先 {{if .Items}} 套一层。











