Gin中{{template}}生效需满足三条件:公共模板文件被LoadHTMLGlob/Files加载、子模板用{{define "xxx"}}声明、主模板用{{template "xxx" .}}调用且名称严格一致。

直接用 {{template}} 就能引入,但路径、定义顺序和模板作用域不配对,页面就空白或报错——这是最常卡住的地方。
模板里怎么写 {{template}} 才有效
必须先在被引入的公共文件里用 {{define "xxx"}} 显式声明区块名,再在主模板里用 {{template "xxx" .}} 调用。点号 . 表示把当前上下文数据透传进去,否则子模板拿不到 .title、.user 这类变量。
-
{{define "header.html"}}和{{template "header.html" .}}中的名称必须完全一致(包括大小写和扩展名) - 如果公共文件在
templates/common/header.html,LoadHTMLGlob("templates/**/*")能加载到,但不能写成{{template "common/header.html" .}}—— Gin 不支持路径形式的 template 名,只认define里的字符串字面量 - 调用时加
.是关键:漏掉就等于传了个空 map 进去,所有字段访问都为 nil
LoadHTMLGlob 的路径模式影响能否找到公共模板
公共模板文件本身得被 LoadHTMLGlob 或 LoadHTMLFiles 加载进内存,否则 {{template}} 找不到定义,运行时静默失败(页面渲染一半就停)。
- 推荐用
r.LoadHTMLGlob("templates/**/*"),确保templates/common/、templates/layouts/全部纳入 - 若只写
r.LoadHTMLGlob("templates/*.html"),则子目录下的common/header.html根本不会被加载,{{template "header.html" .}}会直接忽略(无报错) - 用
LoadHTMLFiles时,必须显式列出所有文件,包括公共模板:r.LoadHTMLFiles("templates/base.html", "templates/common/header.html", "templates/home.html")
嵌套层级深了,.user.Name 突然变空?检查数据传递链
公共模板不是独立执行的,它复用主模板的数据上下文。但如果在 {{template}} 外又套了一层 {{with}} 或 {{range}},当前作用域就变了。
- 比如主模板里有
{{range .articles}}{{template "item.html" .}}{{end}},那item.html拿到的是单个Article结构体,不是整个gin.Hmap - 此时若在
item.html里还想去读.user.Name,就得提前把 user 带进去:{{template "item.html" (dict "article" . "user" $)}}(需注册dict函数),或者改用{{template "item.html" $}}把顶层上下文传下去 - 更稳妥的做法:所有需要跨层级访问的字段,统一挂到顶层 map 里,比如
gin.H{"user": u, "article": a, "sidebar": s},避免嵌套中丢数据
最容易被忽略的是:Gin 的 {{template}} 不做路径解析,只做字符串匹配;而 LoadHTMLGlob 是否覆盖到文件,决定了 define 能否注册成功——这两处任一出错,都不会报错,只会让页面某一块消失。调试时先确认 common/header.html 里有 {{define "header.html"}},再确认 LoadHTMLGlob 的 glob 模式真能扫到它。


















