Revel模板中用{{range}}遍历数组或切片:{{range $index, $value := .Items}}索引{{$index}}值{{$value}}{{end}},不支持传统for循环。

Revel模板里怎么用range遍历数组或切片?
Revel的模板语法基于Go原生text/template,不支持类似JavaScript的for (let i = 0; i 写法。必须用range动作,且要注意它会直接解包——遍历时拿到的是元素值,不是索引+值的组合。
常见错误是写成:{{range .Items}}{{.ID}}{{end}},结果报nil pointer dereference:因为.Items为空切片或为nil时,range不执行,但若模板里后续还依赖.上下文(比如嵌套if里又用了.),就容易出问题。
- 始终先判空:
{{if .Items}}{{range .Items}}...{{end}}{{else}}无数据{{end}} - 需要索引时,用
$i, $v := range .Items(注意变量名前加$,否则会覆盖外层.) - 切片类型必须在Controller中显式传入,不能靠反射自动展开结构体字段里的未导出字段
传入[]string或[]*User到模板,为什么{{.}}渲染为空?
根本原因是Revel默认对模板变量做HTML转义,而{{.}}在range内指代当前元素——如果元素是结构体指针,{{.}}会调用其String()方法(若未定义则输出&{...}格式),但Revel的转义逻辑对指针值处理不稳定,常表现为空白或panic。
- 明确访问字段:
{{.Name}}、{{.Email}},别偷懒用{{.}} - 字符串切片可直接
{{.}},但要防nil:{{if .}}{{.}}{{end}} - 若需原始HTML(如富文本字段),用
{{.Content | safe}},前提是已注册safe函数(Revel 1.x需手动注册,2.x内置)
模板里能用len判断数组长度吗?
可以,但仅限于已知非nil的切片。如果.Items是nil,{{len .Items}}会触发模板执行失败,错误信息是error calling len: len of untyped nil。
- 安全写法是组合
if和len:{{if and .Items (gt (len .Items) 0)}}... - 更推荐用
{{if .Items}}代替len判断,语义清晰且避免nil panic -
len不能用于map或channel,Revel模板里只对slice/array有效
嵌套循环(比如每个User有多个Tag)怎么写?
Revel模板支持多层range,但要注意变量作用域。内层range会覆盖外层的.,所以必须提前把外层关键字段存到临时变量,用$前缀声明。
{{range .Users}}
<div class="user">{{.Name}}</div>
{{with $user := .}}
{{range $user.Tags}}
<span class="tag">{{.Name}}</span>
{{end}}
{{end}}
{{end}}
- 不用
with而直接写{{range .Tags}}会报错:因为内层.已变成Tag对象,不再有.Tags - 如果Tag是
[]*Tag,确保Controller中已加载关联数据(Revel不自动JOIN,需手动查或用预加载) - 深度嵌套建议拆成子模板(
{{template "tag-list" .Tags}}),提升可读性与复用性
最常被忽略的是Controller层的数据准备——模板再怎么写对,如果.Users里每个User的Tags字段是nil切片而非空切片,range照样不执行,页面就静默丢失内容。











