Revel模板不支持直接传多个参数给子模板,需用dict函数将键值对封装为map[string]interface{}后单参数传递,这是官方推荐解法。

Revel模板里不能直接传多个参数给子模板
Go标准html/template只允许{{template}}接收一个参数(即.),Revel沿用这一限制。写{{template "item.html" .User .Role}}会报错:unexpected “.” in template clause。这不是Revel的bug,而是底层模板引擎的设计约束。
用dict函数封装多个变量最实用
注册dict函数后,就能把任意键值对打包成map[string]interface{},再作为单个参数传入子模板。这是官方推荐、社区广泛采用的解法。
在app/init.go的init()函数中添加:
{{.user.Name}}
- 传整个
.:写{{template "item.html" .}},子模板里直接用{{.CurrentUser}}等。问题在于污染作用域,若子模板和父模板字段名冲突(如都叫.ID),结果不可控。 - 传结构体指针:控制器里构造
struct{ User *User; IsAdmin bool }再RenderArgs["data"] = data。但每次调用都要新建类型,维护成本高,且容易忘记导出字段导致模板读不到。 - 拼接JSON字符串:用
M.ToJSON转成字符串再{{. | safeJS}}注入JS上下文。仅适用于前端数据初始化,不能用于HTML渲染逻辑。
这些都不是真正“传多个变量”,只是绕开限制的权宜之计。
嵌套range中传参必须显式声明变量
在{{range}}块里调用子模板,最容易犯的错是以为.还代表外层上下文。实际上.已变成当前迭代项,原.Title、.Count全不可见。
正确做法是用$前缀捕获外层变量,并在dict中显式传入:
{{range $i, $item := .Items}}
{{template "list-item.html" (dict "item" $item "index" $i "title" $.Title "totalCount" $.Count)}}
{{end}}
注意$.Title中的$表示根上下文,不是.Title——后者在range内已被覆盖。漏掉$会导致.Title为空,且无任何错误提示。











