Gin 不支持自动按目录结构映射模板名,必须用 LoadHTMLGlob("templates/*/") 递归加载并配合 {{ define "admin/index.html" }} 显式命名,c.HTML 第二个参数需严格匹配该 define 名(含路径),且加载须在路由注册前完成。

直接说结论:Gin 不支持「自动按目录结构映射模板名」,必须靠 LoadHTMLGlob 的通配符匹配 + 模板内 define 显式命名,才能在多级目录下正确加载同名模板(比如 admin/index.html 和 user/index.html)。
为什么 LoadHTMLGlob("templates/*") 加载不了子目录里的模板
因为 * 只匹配一级路径,templates/admin/index.html 这种路径不会被命中。常见错误是浏览器报错 template: "index.html" is undefined,其实不是模板没找到,而是 Gin 根本没加载它。
-
templates/*→ 只加载templates/index.html、templates/about.html -
templates/**/*→ 才会递归加载templates/admin/index.html、templates/user/detail.html等 - Windows 下部分 Go 版本对
**支持不稳定,建议统一用templates/**/*而非templates/**
define 是多目录同名模板的强制要求
即使你用 LoadHTMLGlob("templates/**/*") 成功加载了 admin/index.html 和 user/index.html,调用 c.HTML(http.StatusOK, "index.html", ...) 时 Gin 仍会冲突 —— 它只认文件名,不认路径。
- 必须在每个 HTML 文件开头用
{{ define "admin/index.html" }}显式声明模板名 - 对应地,
c.HTML第二个参数要写成"admin/index.html",不能省略路径 -
define块必须包裹全部内容,且{{ end }}不可遗漏,否则解析失败无提示
LoadHTMLFiles 适合小项目但要注意路径写法
当模板数少(比如就 3–5 个),用 LoadHTMLFiles 更可控,避免 glob 匹配到不该加载的临时文件。
- 路径必须写全,包括扩展名:
r.LoadHTMLFiles("templates/admin/index.html", "templates/user/profile.html") - 路径是相对于当前工作目录(
os.Getwd()),不是相对于main.go文件位置 - 如果用 IDE 运行,工作目录可能是项目根目录;但用
go run ./cmd/server时,工作目录是./cmd/server所在目录,容易出错
调试时最容易忽略的两个点
一是模板加载时机:必须在 r.GET 注册之前调用 LoadHTMLGlob 或 LoadHTMLFiles,否则路由处理时模板引擎为空;二是 define 名称和 c.HTML 参数必须完全一致,包括大小写和斜杠方向 —— Windows 上写成 "admin\index.html" 会导致找不到模板。











