go模板无法遍历结构体中的切片,通常是因为该字段未导出(首字母小写),导致text/template包忽略该字段;只需将字段名首字母大写并同步更新模板引用即可修复。
在 Go 的 text/template 中,所有被模板访问的字段、方法和变量都必须是导出的(exported)——即名称必须以大写字母开头。这是 Go 反射机制的硬性要求,模板引擎依赖 reflect 包读取数据,而 reflect 无法访问非导出(小写首字母)字段。
在你的示例中,Context 结构体定义为:
type Context struct {
people []Person // ❌ 小写 'p' → 非导出字段 → 模板不可见
}尽管 Person 类型及其字段 Name 和 Senior 均已正确导出,但外层 people 字段不可见,因此 $.people 在模板中求值为 nil 或空值,range 迭代不执行,最终输出为空。
✅ 正确做法是将字段改为导出形式,并同步更新模板表达式:
type Context struct {
People []Person // ✅ 大写 'P' → 导出字段 → 模板可访问
}对应模板需同步修改为:
{{range $i, $x := $.People}} Name={{$x.Name}} Senior={{$x.Senior}} {{end}}完整可运行修正版如下:
package main
import (
"os"
"text/template"
)
type Context struct {
People []Person // ✅ 导出字段
}
type Person struct {
Name string // ✅ 导出
Senior bool // ✅ 导出
}
func main() {
t := template.Must(template.New("RangeExample").P
arse(`
{{range $i, $x := $.People}}
Index={{$i}} Name={{$x.Name}} Senior={{$x.Senior}}
{{end}}
`))
ctx := Context{
People: []Person{
{Name: "Mary", Senior: false},
{Name: "Joseph", Senior: true},
},
}
t.Execute(os.Stdout, ctx)
}? 关键注意事项:
掌握导出规则是 Go 模板开发的第一道门槛。记住:模板可见性 = Go 导出可见性——没有例外。