Buffalo模板中for循环必须用for $item in $items语法,不支持Go的range;$items需非nil切片或映射,变量名必加$,嵌套时避免变量名冲突;空数据需在handler初始化或模板if兜底;索引和长度用$for.index、$for.length;函数需注册,方法调用受限于类型反射。

Buffalo模板里用for循环遍历切片或映射
Buffalo默认使用plush作为模板引擎,不支持Go原生range语法,必须用for关键字——写成for $item in $items,而不是{{range .Items}}。这是新手最常卡住的地方:模板直接报错parse error: unexpected "for",其实是忘了Buffalo的语法不是Go template。
实操时注意三点:
-
$items必须是切片(如[]string、[]User)或映射(map[string]interface{}),不能是nil;传入前在handler里做if items == nil { items = []string{} } - 变量名前必须加
$,比如$user.Name,漏掉会静默失败,渲染为空字符串 - 嵌套循环时,内层变量名别和外层重复,否则会被覆盖,例如外层用
$post,内层就别再用$post当迭代变量
处理空数据时避免模板崩溃
Buffalo的for循环遇到nil切片会panic,错误信息通常是plush: cannot iterate over <nil></nil>。它不会像Go template那样跳过range块,而是直接中断渲染。
安全做法只有两种:
- 在action handler中确保数据非nil:
c.Data["users"] = users前加判断,if users == nil { users = []User{} } - 在模板里用
if兜底:{{ if $users }} {{ for $u in $users }} <div>{{ $u.Name }}</div> {{ end }} {{ else }} <p>No users found.</p> {{ end }}
别依赖for自身判空——它不干这事。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
访问索引和长度:用$for.index和$for.length
Buffalo的for提供隐式$for对象,里面存着当前迭代状态。需要序号、是否首尾、总长时,必须用它,不能自己维护计数器。
常见用法:
- 显示序号:
{{ $for.index + 1 }}(注意从0开始) - 加隔符但末尾不加:
{{ if not $for.last }}, {{ end }} - 只对第一个元素特殊处理:
{{ if $for.first }}<h2>Top User</h2>{{ end }} - 判断是否单条:
{{ if eq $for.length 1 }}Only one item{{ end }}
注意$for只在for块内有效,出块即失效,也不能在if里提前引用。
循环中调用函数或方法要小心作用域
在for块里调用自定义函数(比如formatDate)或结构体方法(比如$user.FullName()),容易遇到function not defined或method not found。
原因通常是:
- 函数没注册到plush上下文:要在
app.go里显式添加,app.Use(plush.Middleware(plush.Options{...}))并传入Funcs: map[string]interface{}{"formatDate": formatDate} - 方法调用失败是因为
$user是interface{}类型,plush无法自动反射结构体方法;得把方法逻辑移到函数里,或确保传入的是具体类型指针(如*User)并已注册该类型的接收器 - 嵌套循环中若内层用了外层变量名(比如都叫
$item),外层方法调用可能绑定错对象
最稳的方式是:所有复杂逻辑提前在handler里计算好,模板只做纯展示。循环里只读字段、调简单函数,别碰状态或副作用。

















