Gin模板中直接用len函数即可获取切片、数组、map等长度,无需注册;需确保传入非nil集合类型,循环内用$访问外层上下文获取总长,避免误用.导致取当前元素长度。

模板里直接用 len 函数就行
Gin 默认使用的 Go 模板引擎原生支持 len,只要传入的是切片、数组、map、字符串或 channel,就能直接调用。不需要额外注册函数,也不依赖 Gin 版本(1.9+ 和旧版都一样)。
常见错误是传了 nil 或非集合类型(比如 struct 指针),这时 len 会 panic,但模板中不会报错,而是静默渲染为空——容易误以为“没生效”,其实是数据没传对。
- 确保后端传的是真实切片,比如
c.HTML(200, "index.html", gin.H{"items": []string{"a", "b"}}) - 模板中写
{{len .items}},不是{{len(.items)}}(Go 模板不支持括号调用) - 如果
.items可能为nil,先判空:{{if .items}}{{len .items}}{{else}}0{{end}}
为什么 range 里不能直接用 len
在 {{range .items}} 循环内部,. 指向当前元素,不是原切片,所以 {{len .}} 是当前元素的长度(比如字符串长度),不是整个列表长度。
想在循环里知道总数量,得把长度提前算好传进去,或者用 $ 访问外层上下文:
{{ $total := len .items }}
{{range .items}}
<div>第 {{inc $index}} / {{$total}} 项</div>
{{end}}
注意:$index 是 range 内置变量,从 0 开始;inc 是 Go 模板内置函数(Go 1.19+),旧版本需手动加 1 或改用 add $index 1。
自定义函数替代方案(不推荐但可行)
极少数情况需要更复杂的逻辑(比如嵌套结构取 length),可以注册自定义函数:
func length(v interface{}) int {
if v == nil {
return 0
}
return reflect.ValueOf(v).Len()
}
// 注册到模板
t := template.New("").Funcs(template.FuncMap{"length": length})
engine := gin.Default()
engine.SetHTMLTemplate(t)
但没必要——len 已足够,且自定义函数会让模板行为不透明,调试困难。只有当你必须处理 nil 安全且不想在每个模板里写 if 判空时才考虑。
常见报错和排查点
如果看到空白或模板渲染失败,重点查这三处:
- 后端传的字段名大小写是否匹配?Go 结构体字段必须首字母大写才能导出,
Items []string对应模板里是.Items,不是.items - 传的是指针还是值?
&[]string{}传过去,len会作用于指针本身(结果是 1),不是底层数组 - 模板文件是否被正确加载?Gin 默认只读
./templates/**/*,路径错或后缀不是.html会导致变量全为空
最稳妥的做法:先在模板顶部加 {{printf "%#v" .items}} 看实际值,再决定怎么取长度。











