loadhtmlglob("templates/")找不到子目录模板,因单个不递归匹配;应改用"templates/*/"或分层loadhtmlglob;且必须在路由注册前调用,c.html中模板名须严格匹配文件名(含扩展名)。

模板解析失败,八成是 LoadHTMLGlob 或 LoadHTMLFiles 路径写错了,或者没在调用 c.HTML 前完成加载。
为什么 LoadHTMLGlob("templates/*") 找不到子目录里的模板?
Go 的 filepath.Glob 规则里,单个 * 只匹配当前目录下的文件,不进子目录;** 才递归匹配。所以 "templates/*" 会漏掉 templates/user/profile.html 这类路径。
- 正确写法是
router.LoadHTMLGlob("templates/**/*") - 如果只有一级模板(全在
templates/下),用"templates/*.html"更安全,避免误加载隐藏文件或备份文件 - Windows 下路径分隔符不影响,
/**/*在所有平台都有效
c.HTML 报错 “template not found” 怎么排查?
这个错误不是运行时报的,而是在第一次调用 c.HTML 时才触发模板查找——也就是说,加载阶段不报错,渲染时才崩。
- 检查
LoadHTMLGlob是否在r.GET之前执行(顺序很重要) - 确认传给
c.HTML的模板名(第二个参数)和磁盘上文件名**完全一致**,包括大小写和扩展名,比如"index.html"≠"Index.html" - 用
os.ReadDir("templates")手动验证目录是否存在、文件是否可读 - 注意:Gin 不会自动补扩展名,
c.HTML(200, "index", data)会失败,必须写"index.html"
嵌套模板(define/template)为什么不生效?
嵌套依赖两个前提:所有参与嵌套的模板文件必须被 LoadHTMLGlob 或 LoadHTMLFiles 一次性加载;且 define 名称在所有已加载模板中唯一。
- 如果只加载了
home.html,但它{{template "header"}}引用了未加载的header.html,就会静默失败(页面空白或报错) -
{{define "layout"}}...{{end}}和{{template "layout" .}}必须在同一个加载批次里,不能分开两次LoadHTMLFiles - 调试技巧:在模板里加
{{printf "%#v" .}}看传入数据结构,确认上下文是否传递到位
最常被忽略的是加载时机和路径通配精度——很多人改完模板以为 reload 就行,其实 Gin 启动后不会热重载模板,改了 LoadHTMLGlob 路径必须重启进程才能生效。











