必须显式调用LoadHTMLGlob或LoadHTMLFiles加载模板,否则c.HTML()会panic;模板名须与{{define}}内名称严格一致(含路径、大小写),且路径相对于可执行文件目录。

模板文件必须用 LoadHTMLGlob 或 LoadHTMLFiles 显式加载
Gin 不会自动扫描或热加载模板文件,没调用加载方法就直接 c.HTML(),会 panic 报错:template: "xxx.html" is undefined。常见错误是只写了渲染逻辑,忘了在 gin.Engine 初始化时加载模板。
-
LoadHTMLGlob("templates/**/*")最常用,支持嵌套目录(如templates/admin/index.html),通配符需包含扩展名,比如"templates/*.html"或"templates/**/*.tmpl" -
LoadHTMLFiles("templates/index.html", "templates/layout.html")适合模板少、路径明确的场景;但一旦漏写某个模板,运行时才暴露问题 - 路径是相对于 **可执行文件所在目录**,不是
main.go所在目录 —— 如果用go run main.go,就是当前命令行路径;如果编译后运行,则是二进制文件所在路径
c.HTML() 的模板名不带路径前缀,但必须与 define 名一致
模板里用 {{ define "users/index.html" }},c.HTML() 第二个参数就得传 "users/index.html",不能写成 "templates/users/index.html" 或 "index.html"。Gin 内部靠这个字符串匹配 define 块,大小写和斜杠都敏感。
- 如果模板中用了
{{ define "home" }},那调用时就是c.HTML(200, "home", data) - 多个
define可以共存于一个文件,但每个名字必须唯一;重复定义会导致最后加载的那个覆盖前面的 - 推荐统一用文件路径作为
define名(如"admin/dashboard.html"),避免命名冲突,也方便 IDE 跳转
前端传参给模板时,gin.H 和结构体字段名要匹配模板中的 .Field
模板里写 {{ .Title }},数据里就必须有 Title 字段。Go 的 struct 字段必须首字母大写(导出),且 tag 里不能干扰 html/template 解析 —— json: tag 不影响,但 template: 或自定义 tag 若未处理,可能让字段不可见。
-
gin.H{"Title": "首页"}是最简方式,适合简单页面;字段名区分大小写,"title"小写无法被{{ .Title }}访问 - 用结构体更类型安全:
type PageData struct { Title string; Items []string },但注意字段必须是导出的(大写开头) - 嵌套字段如
{{ .User.Name }}要求User是导出字段,且其类型也有导出的Name字段;map[string]interface{}也能用,但缺乏编译期检查
静态资源(CSS/JS)需单独配置 StaticFS,模板里路径不能硬编码
模板中写 <link rel="stylesheet" href="/static/css/index.css"> 没问题,但前提是 Gin 已通过 r.StaticFS("/static", http.Dir("./static")) 暴露该目录。否则浏览器 404,样式不生效,而服务端完全无报错提示。
立即学习“go语言免费学习笔记(深入)”;
- 静态目录路径(如
"./static")也是相对可执行文件位置,和模板路径规则一致 - 不要在模板里写
href="static/css/..."(缺前缀/),否则变成相对路径,容易因路由层级出错 - 开发时可加
r.Static("/static", "./static")简化写法;生产环境建议用StaticFS配合http.Dir更可控 - CSS 文件里引用的字体、图片等,同样要确保在静态服务路径下,且路径与模板中一致


















