在Go模板中,当通过Execute传入切片作为数据源时,模板上下文中的“点”(.)即代表该切片本身;因此{{range .}}即可遍历切片,而{{.Files}}会报错——因为切片没有名为Files的字段。
在go模板中,当通过execute传入切片作为数据源时,模板上下文中的“点”(`.`)即代表该切片本身;因此`{{range .}}`即可遍历切片,而`{{.files}}`会报错——因为切片没有名为files的字段。
Go模板的执行上下文由template.Execute()传入的数据决定。当你调用t.Execute(os.Stdout, Files)时,Files(类型为[]File)成为模板的根数据(即管道起始值.)。此时模板中任何以.开头的表达式,都是在该切片上求值——而切片类型既无字段Files,也无同名方法,故{{.Files}}必然触发can't evaluate field Files in type []main.File panic。
✅ 正确做法是直接使用{{range .}}遍历切片,此时每次迭代中.自动绑定为当前File结构体实例:
type File struct {
FileName string
FileSize int64
}
var Files = []File{
{"data.txt", 123},
{"prog.txt", 5678},
}
const tmpl = `
{{range .}}
file name: {{.FileName}}, size: {{.FileSize}}
{{end}}
`
t := template.Must(template.New("list").Parse(tmpl))
err := t.Execute(os.Stdout, Files)
if err != nil {
panic(err)
}输出结果为:
file name: data.txt, size: 123 file name: prog.txt, size: 5678
⚠️ 注意事项:
- 不要误以为模板数据必须是结构体或带字段的容器——切片、map、基本类型均可直接作为根数据;
- 若需嵌套访问(如传入map[string]interface{}{"Files": Files}),才应使用{{range .Files}},但此时根数据类型已改变;
- 在{{range}}内部,.始终代表当前迭代项(这里是File),可安全访问其导出字段(如.FileName);
- 所有字段名必须首字母大写(导出),否则模板无法访问(Go反射机制限制)。
掌握.在不同作用域下的绑定规则,是写出健壮Go模板的关键基础。

















