
在Go模板中,range语句的上下文取决于传入Execute()的数据类型:若传入的是切片,则模板中的.即代表该切片本身,而非结构体字段,因此应直接用{{range .}}而非{{range .Files}}。
在go模板中,`range`语句的上下文取决于传入`execute()`的数据类型:若传入的是切片,则模板中的`.`即代表该切片本身,而非结构体字段,因此应直接用`{{range .}}`而非`{{range .files}}`。
当你调用 t.Execute(os.Stdout, Files) 时,Files(类型为 []File)成为模板执行的根数据(root data),此时模板管道中的 . 就等价于整个切片 []File,而不是某个包含 Files 字段的结构体。因此 {{.Files}} 会报错:“can't evaluate field Files in type []main.File”——因为切片类型没有名为 Files 的字段。
✅ 正确做法是:直接在 range 中使用 {{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
⚠️ 注意事项:
- 若需传入更复杂的上下文(如含 Files 字段的配置结构体),则必须显式构造该结构并传入,例如:struct{ Files []File }{Files: Files},此时模板中才可写 {{range .Files}};
- 模板中 . 的含义始终由 Execute() 的第二个参数决定,与变量名无关;
- range 内部的 . 是当前迭代项,外部的 . 是传入的根数据,二者作用域严格分离;
- 建议在模板中避免裸用 {{.}}(会输出结构体默认字符串表示),而应明确访问字段以提升可读性与健壮性。
掌握 . 在模板不同层级的绑定逻辑,是写出清晰、可维护 Go 模板的关键基础。











