Gin 必须显式调用 LoadHTMLGlob 或 LoadHTMLFiles 加载模板,否则 c.HTML() 会 panic 报“模板未定义”;模板路径需相对于工作目录,推荐使用 templates/ 目录,且加载时路径与模板名严格一致(含子目录),如 templates/admin/index.html 注册后模板名为 admin/index.html。

必须显式加载模板文件,Gin 不会自动扫描或默认启用任何模板。不调用 LoadHTMLGlob 或 LoadHTMLFiles 就直接用 c.HTML(),会 panic 报错:html/template: "xxx.tmpl" is undefined。
模板文件路径怎么写才有效
Gin 的模板加载依赖文件系统路径,不是 Go 包路径;路径需相对于当前工作目录(即 go run 所在目录),不是 main.go 所在目录。
- 推荐统一用
templates/目录,放在项目根目录下 -
r.LoadHTMLGlob("templates/*.tmpl"):只匹配一级子目录下的.tmpl文件 -
r.LoadHTMLGlob("templates/**/*"):支持任意深度嵌套(如templates/admin/user/edit.tmpl),但注意**是 Gin 内部解析的通配符,不是 shell 语法 - 避免使用绝对路径(如
/home/user/myapp/templates/...),会导致部署时不可移植
LoadHTMLGlob 和 LoadHTMLFiles 的区别
两者都注册模板到 Gin 的 HTMLRender,但行为不同,选错会导致部分模板找不到。
-
LoadHTMLGlob("templates/**/*.html"):自动 glob 展开所有匹配文件,按文件名注册模板名(如templates/user/list.html→ 模板名为user/list.html) -
LoadHTMLFiles("templates/base.html", "templates/index.html"):只加载列出的文件,模板名就是传入的文件名(不含路径),容易因路径不一致导致template: "index.html" not found - 混合使用会覆盖——后调用的会覆盖先注册的同名模板,调试时注意检查日志是否重复加载
模板里用 {{define}} 定义局部模板,为什么 template 调用失败
根本原因:Gin 加载时不会自动解析嵌套 {{define}} 模板之间的依赖关系;所有被 {{template}} 引用的命名模板,必须和主模板一起被同一轮 LoadHTMLGlob 或 LoadHTMLFiles 加载。
- 例如
layouts/base.tmpl中有{{define "content"}},而pages/home.tmpl中写{{template "content" .}},那么两个文件必须同时出现在同一个LoadHTMLGlob("templates/**/*")调用中 - 如果只加载
pages/home.tmpl,Gin 会报错:template: "content" is not defined - 不支持跨
LoadHTMLFiles调用引用:两次分别调用LoadHTMLFiles("base.tmpl")和LoadHTMLFiles("home.tmpl"),home.tmpl无法识别base.tmpl里的define
最容易被忽略的是:模板名区分大小写且严格匹配路径结构;比如 templates/Admin/dashboard.tmpl 注册后的模板名是 Admin/dashboard.tmpl,不是 dashboard.tmpl,调用 c.HTML(200, "dashboard.tmpl", ...) 必然失败。


















