
本文详解如何在 Go 的 text/template 中正确遍历结构体切片([]struct),并通过 range 动作访问每个结构体字段,实现清晰、安全的 HTML 或文本渲染。
本文详解如何在 go 的 `text/template` 中正确遍历结构体切片(`[]struct`),并通过 `range` 动作访问每个结构体字段,实现清晰、安全的 html 或文本渲染。
Go 模板不支持直接索引访问切片(如 .List[0].ID),必须使用 range 动作进行迭代。核心要点是:range 可同时绑定索引和元素变量,推荐显式命名以提升可读性与维护性。
以下是一个标准、可运行的示例:
package main
import (
"fmt"
"os"
"text/template"
)
type MyType struct { // 注意:字段名首字母大写才能导出(模板中可访问)
ID string
Name string
Test string
}
func main() {
list := []MyType{
{"id1", "name1", "test1"},
{"id2", "name2", "test2"},
}
tmpl := `
<table border="1">
{{range $index, $item := .}}
<tr>
<td>{{ $item.ID }}</td>
<td>{{ $item.Name }}</td>
<td>{{ $item.Test }}</td>
</tr>
{{end}}
</table>
`
t := template.Must(template.New("list").Parse(tmpl))
if err := t.Execute(os.Stdout, list); err != nil {
fmt.Fatal("模板执行失败:", err)
}
}✅ 关键说明:
- . 在 range 中代表传入的根数据(即 []MyType 切片);
- {{range $index, $item := .}} 中 $index 是当前索引(可省略,用 _ 占位),$item 是当前结构体实例;
- 所有结构体字段必须是导出字段(首字母大写),否则模板无法访问(如原问题中 Name 和 Test 缺少类型声明且未导出,会导致渲染为空);
- 若只需元素无需索引,可简写为 {{range .}},此时 . 指向当前结构体,可直接写 {{.ID}};但显式命名(如 $item.ID)更利于嵌套模板与逻辑扩展。
⚠️ 常见陷阱提醒:
- 忘记字段导出 → 模板中输出为空字符串;
- 使用未定义变量(如 {{.Name}} 在 range 外作用域无效);
- 混淆 . 的上下文:在 range 内部 . 指当前元素,外部 . 指传入的整个切片;
- 未处理空切片 → range 会自然跳过,安全,但建议前端加 {{if .}}...{{else}}暂无数据{{end}} 提升用户体验。
掌握 range 与结构体字段访问,即可高效构建动态列表、表格、卡片等模板场景,是 Go Web 开发与 CLI 工具生成内容的基础能力。


















