
Go 模板中访问嵌套 range 需确保结构体字段类型与 JSON 数据严格一致:若 keywords 是字符串切片,结构体中必须定义为 []string,模板内用 {{range .Keywords}}{{.}}{{end}} 直接遍历,而非错误地使用 $key, $item := range。
go 模板中访问嵌套 range 需确保结构体字段类型与 json 数据严格一致:若 keywords 是字符串切片,结构体中必须定义为 `[]string`,模板内用 `{{range .keywords}}{{.}}{{end}}` 直接遍历,而非错误地使用 `$key, $item := range`。
在 Go 模板中实现多层嵌套数据遍历(如 .Resume.Skills → .Keywords),关键在于数据结构、JSON 解析与模板语法三者的一致性。你遇到的输出为 {} 或 0 1 2 等异常结果,根本原因在于 Go 结构体字段类型与实际 JSON 数据不匹配。
? 问题根源分析
你的原始 JSON 中 "keywords" 是一个纯字符串数组:
"keywords": ["CSS", "HTML", "Javascript"]
但结构体却定义为:
type SkillsInfo struct {
Name string
Level string
Keywords []KeywordsInfo // ❌ 错误:期望对象切片,实际是字符串切片
}
而 KeywordsInfo 是一个含 Keyword string 的结构体——这会导致 json.Unmarshal 无法将字符串 "CSS" 赋值给 KeywordsInfo 类型,最终 Keywords 字段保持零值(空切片),模板中 range 无内容可遍历,甚至可能因类型不匹配引发静默失败或索引式输出(如 0, 1, 2)。
✅ 正确解决方案
1. 调整 Go 结构体以匹配 JSON
type SkillsInfo struct {
Name string `json:"name"`
Level string `json:"level"`
Keywords []string `json:"keywords"` // ✅ 直接映射字符串切片
}
注意添加 json 标签确保字段名大小写匹配(JSON 小写,Go 字段首字母大写)。
2. 简化模板语法
无需引入 $key, $item 变量——因为 []string 的 range 迭代的是元素值本身,. 即代表当前字符串:
{{range .Resume.Skills}}
<h3>{{.Name}} ({{.Level}})</h3>
-
{{range .Keywords}}
- {{.}} {{end}}
3. 完整可运行示例(含 JSON 解析)
package main
import (
"html/template"
"log"
"os"
)
type ResumeJson struct {
Skills []SkillsInfo `json:"skills"`
}
type SkillsInfo struct {
Name string `json:"name"`
Level string `json:"level"`
Keywords []string `json:"keywords"`
}
func main() {
const jsonInput = `{
"skills": [{
"name": "Web Development",
"level": "Master",
"keywords": ["CSS", "HTML", "JavaScript"]
}]
}`
var resume ResumeJson
if err := json.Unmarshal([]byte(jsonInput), &resume); err != nil {
log.Fatal(err)
}
t := template.Must(template.New("skills").Parse(`
{{range .Skills}}
<strong>{{.Name}}</strong> — {{.Level}}
-
{{range .Keywords}}
- {{.}} {{end}}
输出:
<strong>Web Development</strong> — Master
- CSS
- HTML
- JavaScript
⚠️ 注意事项
- 永远校验 JSON → struct 映射:使用 https://www.php.cn/link/4daf3131a3b73237edccfc5c6acbd7ad 辅助生成准确结构体;
- 避免过度解构:对 []string 或 []int,range 中直接用 {{.}};仅当遍历 map 或需索引时才用 {{range $i, $v := .Slice}};
- 启用模板调试:在开发阶段临时添加 {{printf "%#v" .Keywords}} 查看实际值,快速定位空切片或类型错误;
- 大小写敏感:Go 模板中 .Keywords 要求结构体字段导出(首字母大写),且 json tag 必须与 JSON 键名完全一致(包括大小写)。
遵循“数据先行,结构同步,模板极简”原则,即可稳健处理任意深度的嵌套 range 场景。











