revel不支持直接用html/template.parse,必须用revel.rendertemplate解析运行时字符串模板,它复用已注册函数和上下文;但仅限单层内联、变量名严格匹配、错误提示简陋;复杂场景应预编译命名模板。

Go标准库的template.Parse不能直接用在Revel模板中
Revel不复用html/template的顶层Parse接口来执行运行时字符串模板,因为它的模板系统在启动时已全部预编译并缓存到revel.TemplateCache中。你若手动调用template.New("").Parse("{{.Name}}"),得到的是一个孤立的*template.Template实例,它无法访问Revel注册的dict、eq、field等内置函数,更不会识别.RenderArgs上下文。
必须用revel.RenderTemplate解析运行时字符串
Revel提供revel.RenderTemplate函数,专为服务端动态拼接模板字符串后渲染设计。它会复用当前应用已注册的所有模板函数和全局上下文。
- 第一个参数是任意合法的Go模板字符串,如
"Hello {{.Name | upper}}" - 第二个参数是数据源,通常传
c.RenderArgs(控制器已准备好的map)或自定义map[string]interface{} - 返回值是
string,不是revel.Result,需手动包装成revel.RenderText或写入响应体
示例:
func (c App) Dynamic() revel.Result {
tmplStr := "{{if eq .Role \"admin\"}}<b>Admin</b>{{else}}User{{end}}"
rendered, err := revel.RenderTemplate(tmplStr, c.RenderArgs)
if err != nil {
return c.RenderError("template parse failed: " + err.Error())
}
return c.RenderText(rendered)
}
注意revel.RenderTemplate的三个限制
这个函数看似灵活,但实际使用中容易踩坑:
-
tmplStr中不能含{{template}}或{{define}}——它只支持单层内联模板,不支持嵌套或子模板引用 - 所有变量名必须与
c.RenderArgs键完全一致,且区分大小写;写{{.name}}而传map[string]interface{}{"Name": "x"}会静默输出空字符串 - 若字符串含语法错误(如漏
{{、未闭合if),err非nil,但错误信息极简,仅类似"unexpected EOF",需人工逐字符检查
更安全的做法:预编译成命名模板再Execute
如果字符串模板内容较复杂或复用频繁,推荐提前注册为命名模板,而非每次RenderTemplate。这能提前暴露语法错误,也利于调试。
- 在
app/init.go的init()中添加:revel.AddTemplate("dynamic_email", "Dear {{.User}}, your order {{.ID}} is {{.Status}}.") - 在控制器中调用:
buf := &bytes.Buffer{}; revel.GetTemplate("dynamic_email").Execute(buf, c.RenderArgs); return c.RenderText(buf.String()) - 好处:模板在启动时即校验,错误可立即发现;支持
{{template}}和{{define}};性能略优(避免重复Parse)
真正动态的场景极少,多数所谓“运行时模板”其实是配置项拼接——这时候该用fmt.Sprintf或text/template独立实例,而不是强塞进Revel模板体系。











