Gin 必须显式调用 LoadHTMLGlob 或 LoadHTMLFiles 启用 c.HTML(),否则 panic;模板路径需匹配 glob 模式,注意递归、前缀、斜杠规范;templateName 匹配 define 名或文件相对路径名;需注册 safe 函数输出原始 HTML;模板加载须在路由注册前完成。

Gin 默认不自动加载任何模板文件,必须显式调用 LoadHTMLGlob 或 LoadHTMLFiles 才能启用 c.HTML() 渲染功能,否则会 panic 报错 template: "xxx" is undefined。
模板文件路径与加载模式必须匹配
常见错误是模板路径写错或 glob 模式没覆盖到目标文件。Gin 加载时不会报错提示“找不到文件”,而是静默跳过——导致后续 c.HTML() 调用失败。
-
r.LoadHTMLGlob("templates/*.html")只匹配templates/一级下的.html文件,不递归子目录 - 要加载
templates/users/index.html,得用r.LoadHTMLGlob("templates/**/*")或r.LoadHTMLGlob("templates/*/*.html") - 路径中不能漏掉
./前缀,"templates/*.html"和"./templates/*.html"在某些工作目录下行为不同 - Windows 下注意反斜杠
\不被 glob 支持,统一用正斜杠/
模板名必须与 define 名或文件名一致
Gin 的 c.HTML(status, templateName, data) 中的 templateName 参数,实际匹配的是模板的“注册名”。这个名默认是文件路径(不含扩展名),但受 define 影响。
- 如果模板里写了
{{define "user/list"}},那必须用c.HTML(200, "user/list", data),不能写成"user/list.html"或"list" - 没写
define时,Gin 自动以相对路径为名:如templates/admin/dashboard.tmpl→ 名为"admin/dashboard" - 多个文件定义同名
define会冲突,Gin 启动时 panic,错误信息含template: redefinition
动态内容渲染要注意转义和自定义函数
Go 的 html/template 默认对所有 {{.X}} 输出做 HTML 转义,防止 XSS——这很安全,但也会把你想插入的 HTML 字符串(比如富文本)变成纯文本。
- 要原样输出 HTML,用
{{.Content | safe}},但必须先注册safe函数:r.SetFuncMap(template.FuncMap{"safe": func(s string) template.HTML { return template.HTML(s) }}) - 日期、金额等格式化建议封装为模板函数,而不是在 handler 里提前转成字符串——避免时区/本地化问题
- 切片遍历用
{{range .Items}},注意.Items为空时range内容不渲染,无需额外判空 - 嵌套结构取值如
{{.User.Profile.Avatar}},若中间某层为nil,模板会静默失败并跳过整段,不是 panic
最易忽略的是:模板加载必须在任何路由注册之前完成;一旦 r.Run() 启动,再改模板文件不会热更新,必须重启进程。











