
在Go模板中,当通过Execute传入切片作为数据源时,模板上下文中的.即代表该切片本身,因此应直接对.使用range,而非错误地写成.Files——后者会因切片无Files字段而触发panic。
在go模板中,当通过execute传入切片作为数据源时,模板上下文中的`.`即代表该切片本身,因此应直接对`.`使用range,而非错误地写成`.files`——后者会因切片无files字段而触发panic。
Go模板的执行上下文(pipeline)起始值由template.Execute(data)的data参数决定。当你传入Files(类型为[]File)时,模板中初始的.就是这个切片,而非一个包含Files字段的结构体。因此,{{.Files}}会尝试从[]File类型中查找名为Files的字段或方法,这显然不存在,从而导致运行时panic:
can't evaluate field Files in type []main.File
✅ 正确做法是:直接对.使用range,让每次迭代的.自动绑定到当前File元素:
const tmpl = `
{{range .}}
file name: {{.FileName}}, size: {{.FileSize}}
{{end}}
`
完整可运行示例:
一款AI音频处理工具,主要用于通过向 `toingg/make_campaign` API 发送 POST 请求,提交用户提供的 JSON 数据,创建并启动 Toingg 语音呼叫活动,适用于 Codex 将活动简报……,适合需要提升相关任务效率的用户。
package main
import (
"os"
"text/template"
)
type File struct {
FileName string
FileSize int64
}
func main() {
Files := []File{
{"data.txt", 123},
{"prog.go", 5678},
{"config.json", 987},
}
const tmpl = `
{{range .}}
file name: {{.FileName}}, size: {{.FileSize}} bytes
{{end}}
`
t := template.Must(template.New("list").Parse(tmpl))
if err := t.Execute(os.Stdout, Files); err != nil {
panic(err)
}
}
输出结果:
file name: data.txt, size: 123 bytes
file name: prog.go, size: 5678 bytes
file name: config.json, size: 987 bytes
⚠️ 注意事项:
- 若需在模板中同时访问原始切片长度或索引,可结合$(根上下文)与$index、$len等变量(如{{range $index, $file := .}});
- 切勿将切片包装进匿名结构体再传入(如struct{ Files []File }{Files}),除非业务逻辑明确需要——这会增加模板复杂度且违背最小原则;
- 模板中{{.}}在range内默认指代当前元素;若需显式引用根数据,使用$(例如{{$}}表示传入的整个切片)。
掌握.在不同作用域下的语义,是写出健壮Go模板的关键基础。










