模板应放在与main.go同级的templates目录,loadhtmlglob pattern推荐写为"templates/*/"以递归加载所有子目录文件;若仅需顶层则用"templates/",注意后缀匹配(如".html")及避免隐藏文件干扰。

模板文件目录怎么放,LoadHTMLGlob 的 pattern 怎么写
模板必须放在 Go 可访问的路径下,且不能在 go build 时被忽略(比如放在 vendor 或未被引用的子模块里)。最稳妥的位置是与 main.go 同级的 templates 目录(也有人用 tpls 或 views,但名字不重要,路径一致才关键)。
LoadHTMLGlob 的 pattern 决定了哪些文件会被加载为模板,它不是 shell glob,而是 Go 的 filepath.Glob 规则:
-
"templates/*":只匹配templates/下一级的 HTML/TMPL 文件,不递归 -
"templates/**/*":匹配所有子目录(如templates/admin/、templates/user/profile.html),这是多级目录的必备写法 -
"templates/*.html":只加载 .html 后缀,忽略 .tmpl 或 .gotmpl - 别写
"./templates/*"—— 开头的.在某些工作目录下会失效,直接用相对路径名即可
常见错误:模板文件明明存在,c.HTML 却报 template: "xxx.html" is undefined。大概率是 pattern 没覆盖到,或文件后缀没被包含(比如你用了 .tmpl 却只写了 *.html)。
c.HTML 的 templateName 参数到底填什么
这个参数不是文件路径,而是模板的“注册名”。Gin 加载模板时,会把每个文件解析为一个命名模板(named template),默认取文件的 basename(不含扩展名),但前提是没用 {{ define }} 显式定义过。
- 如果
templates/news.html是普通写法:<h1>{{.title}}</h1>→ 模板名就是"news.html" - 如果用了
{{ define "admin/dashboard" }}→ 模板名就是"admin/dashboard",和文件路径无关 - 哪怕文件在
templates/web/home.html,只要里面{{ define "home" }},那就要传"home"给c.HTML
混淆点在于:很多人以为 c.HTML(200, "web/home.html", data) 能自动映射到子目录,其实不能——除非你用 **/* 加载并显式 define 了那个名字,否则 Gin 根本不知道 web/home.html 对应哪个模板名。
开发时要不要用 LoadHTMLFiles,还是坚持用 LoadHTMLGlob
LoadHTMLFiles 是精确控制,适合极小项目或调试单个模板;LoadHTMLGlob 是工程常态。区别不只是写法,还有行为差异:
-
LoadHTMLFiles("a.html", "b.html"):只加载列出的文件,顺序无关,但漏一个就渲染失败 -
LoadHTMLGlob("templates/**/*"):自动发现新增文件,无需改代码,适合迭代中频繁增删模板的场景 - 两者都不支持热重载:修改模板文件后必须重启进程(Gin 本身无模板热编译机制)
- 生产环境建议用
LoadHTMLGlob+ 构建时校验(比如 CI 脚本检查templates/下是否有空目录或无效扩展名)
容易被忽略的一点:LoadHTMLGlob 会加载所有匹配文件,包括隐藏文件(如 .DS_Store 或 ~$news.html),可能触发解析错误。建议模板目录保持干净,或用 templates/*.html 限定后缀。
为什么本地能跑,部署后模板总报错
绝大多数线上模板失败,和代码逻辑无关,纯粹是路径或构建上下文问题:
- 二进制部署时,当前工作目录(
os.Getwd())往往不是二进制所在目录,templates/找不到 → 解决方法:用embed.FS打包模板(Go 1.16+),或启动前os.Chdir到二进制目录 - Docker 镜像里没把
templates/复制进去 →Dockerfile必须有COPY templates/ templates/ - CI/CD 构建时用了
go run main.go,但上线用的是go build,而go run的工作目录是源码目录,go build后运行时默认是任意目录 → 不要依赖相对路径,要么 embed,要么传配置项指定模板根路径 - Linux 系统区分大小写:
News.html和news.html是两个文件,c.HTML传错大小写就找不到
真正难排查的,永远不是语法,而是「你以为它在那儿,其实它根本没被加载进来」——先确认 LoadHTMLGlob 返回的错误(它其实会返回 error,但多数教程都忽略了检查),再查文件是否存在、是否可读、是否被 embed 或打包遗漏。











