go模板中不能直接调用len函数,因模板仅支持预定义函数;需在handler中预先计算长度并传入,或用{{range}}...{{else}}安全判空渲染。

Go模板里不能直接用 len 函数判断切片长度
Go 的 html/template 本身不支持调用 Go 内置函数(如 len),所以你在模板里写 {{len .list}} 会报错:function "len" not defined。这不是 Gin 的限制,是 Go 模板引擎的设计规则——只允许使用预定义的函数(如 print、eq、and 等)。
想在模板中“感知长度”,只能靠间接方式:利用 Go 模板对空值的判定逻辑,或提前把长度算好传进去。
用 {{if .list}} 判空,但要注意 nil 和空切片的区别
{{if .list}} 能判断的是“是否为 empty”,而 Go 模板把以下值都视为 empty:
-
nil切片(如var s []string = nil) - 长度为 0 的切片(
[]string{}) - 空字符串
"" -
nilmap(map[string]int(nil))
但注意:map[string]int{}(空 map)不是 empty,{{if .m}} 会为 true。所以对切片来说,{{if .list}} 可以安全用于“有无数据”的粗略判断,但无法区分 nil 和 [] ——通常业务中也不需要区分。
更稳妥的写法是:
{{if .list}}
{{range .list}}...{{end}}
{{else}}
<span>暂无数据</span>
{{end}}
真要比较具体长度?提前计算并传入字段
如果必须判断“是否等于 3”或“是否大于 5”,别在模板里硬搞,Go 模板不适合做数值逻辑。正确做法是在 handler 中算好:
- 传一个
HasItems布尔字段 - 传一个
ListLen整数字段 - 或者用
gin.H构造 map,显式带长度信息
例如:
func handler(c *gin.Context) {
data := []string{"a", "b"}
c.HTML(200, "page.html", gin.H{
"list": data,
"len": len(data), // ← 显式传入
"hasData": len(data) > 0,
})
}
模板中就能写:
{{if eq .len 2}}刚好两个{{end}}
{{if gt .len 10}}数据太多,已截断{{end}}
为什么不用 {{range}} 的 {{else}} 分支就够了
90% 的场景下,你根本不需要知道具体数字,只需要“有就渲染,没有就提示”。这时 {{range}} 自带的 {{else}} 就是最简洁、最健壮的选择:
{{range .items}}
<div>{{.Name}}</div>
{{else}}
<p class="empty">列表为空</p>
{{end}}
它天然兼容 nil 切片、空切片、甚至未定义字段(只要传的是 nil 或空值,就不会 panic)。比所有 {{if}} 嵌套都可靠——因为 {{range}} 内部做了安全判空,不会触发 nil pointer dereference。
真正容易被忽略的是:很多人图省事只写 {{if .list}},却忘了后续 {{range .list}} 一旦 .list 是 nil,就会直接 500 报错。用 {{range}}...{{else}} 一揽子解决判空 + 渲染 + 容错。











