go模板继承需同一template实例解析所有文件,否则报“undefined”;正确写法是t:=template.new("").parsefiles("layout.html","page.html"),或用parseglob避免顺序问题。

Go 的 html/template 没有原生模板继承,所谓“继承”是靠 define + template + 同一实例解析实现的;如果子模板调用时报 template: "xxx" is not defined,基本就是模板没被加载进同一个 *template.Template 实例。
为什么 ParseFiles("layout.html", "page.html") 还是报 undefined?
因为 template.ParseFiles 默认返回一个新模板实例,但不会自动把所有 define 块注册到全局模板树里——除非你显式用 template.New("") 打头,再链式调用 ParseFiles。
-
template.ParseFiles("a.html", "b.html"):返回的是以a.html为根名的新实例,b.html里的define不会被识别 - 正确写法是:
t := template.New("").ParseFiles("layout.html", "page.html"),或更明确地:t := template.Must(template.New("").ParseFiles("layout.html", "page.html")) - 文件顺序无关,但路径必须可读;重复调用
ParseFiles会覆盖已有模板,不是叠加 - 如果用
ParseGlob("templates/*.html"),更省心,所有匹配文件自动进同一实例
如何用 block 替代 define/template 实现 fallback?
{{block "name" .}} 是 {{define "name"}}...{{end}} 和 {{template "name" .}} 的组合语法,关键在它自带 fallback:当没有同名 define 时,直接渲染 block 内容;而纯 template 调用会 panic。
- 父模板中写:
{{block "header" .}}<h1>Default Header</h1>{{end}} - 子模板中写:
{{define "header"}}<h1>{{.Title}}</h1>{{end}},就会覆盖默认内容 - 如果子模板漏写
define "header",页面仍能安全渲染 fallback,不崩 -
block必须和define在同一模板实例里,否则 fallback 生效但子定义无效
多子模板共存时怎么避免 define 名冲突?
所有 define 名在同一个模板实例里是全局唯一的,header.html 和 footer.html 都定义 "content" 就会互相覆盖。
- 推荐按文件+语义命名:
{{define "header.html"}}、{{define "footer.html"}} - 或者统一加前缀:
{{define "layout/header"}}、{{define "layout/footer"}} - 不要依赖
ParseFiles自动用文件名当模板名——它只对顶层模板生效,define块名完全独立 - 若需动态切换子模板(比如不同页面用不同侧边栏),别硬塞多个
define,改用{{template .SidebarName .}}+ 传参控制
嵌套模板传参时 . 到底代表什么?
{{template "name" .}} 中的 . 是当前作用域的根数据,不是原始传入的整个结构体——子模板内部访问 .Title,拿到的是你传进去的那个值的 Title 字段,不是主模板上下文的。
- 主模板传
{{template "card" .Post}},子模板里.就是.Post对象,{{.Title}}等价于{{.Post.Title}} - 要传多个字段,用
dict函数(Go 1.19+):{{template "alert" (dict "type" "error" "msg" .ErrorMsg)}} - 自定义函数注册方式:
t.Funcs(template.FuncMap{"dict": dictFunc}),dictFunc需自己实现 - 别在子模板里试图访问
$.User.Name这种跨层级字段——$是根,但传参后子模板的.已被重置
最容易被忽略的一点:模板复用的安全边界不在语法,而在加载时机——所有 define 必须在 Execute 前完成注册,且必须属于同一个 *template.Template 实例;运行时无法动态添加,reload 也要重建整个实例。











