
在 go 的 `html/template` 中,使用 `{{ template "name" }}` 语法包含子模板时,默认不会自动继承父模板的数据上下文;必须显式传入当前上下文(如 `.`)才能使变量在子模板中可用。
当你在 index.tpl 中写 {{ template "head" }},Go 模板引擎会以 空上下文(nil) 执行 "head" 模板——这意味着 {{ .Title }} 在 head.tpl 中求值为 ""(空字符串),因此
✅ 正确做法是:显式将当前数据结构传递给被包含的模板:
{{ template "head" . }}其中 . 表示当前执行上下文(即 Page{Title: "This is title", Desc: "Desc"}),这样 head.tpl 就能正常访问 .Title 和 .Desc。
? 修改后的 index.tpl(关键行已加粗):
立即学习“前端免费学习笔记(深入)”;
{{ define "index" }}
**{{ template "head" . }}**
Main info:
Title: {{ .Title }}
Desc: {{ .Desc }}
{{ end }}无需改动 head.tpl,它保持原样即可:
{{ define "head" }}
{{ .Title }}
{{ end }}⚠️ 注意事项:
- {{ template "name" }}(无参数) → 子模板接收 nil 上下文;
- {{ template "name" . }} → 子模板接收与父模板相同的结构体实例;
- 若需传入部分字段或新结构,也可用 {{ template "name" map "title" .Title }} 或自定义结构体,但通常直接传 . 最简洁可靠;
- 所有被 define 声明的模板(如 "head")都是独立作用域,不共享上下文,必须显式传递。
? 小技巧:你还可以在包含时临时修改上下文,例如 {{ template "head" (struct{Title string}{"Custom Title"}) }},适用于需要定制化渲染的场景。
总结:Go 模板的 template 动作默认不透传数据,这是设计上的显式性保障——避免隐式依赖和意外行为。养成 {{ template "xxx" . }} 的习惯,是编写健壮、可维护模板的基础。









