Gin模板渲染必须显式加载模板文件,否则c.HTML()会报“template is undefined”错误;需在gin.Default()后、路由注册前调用LoadHTMLGlob或LoadHTMLFiles,路径相对二进制运行目录,静态资源须单独配置r.Static()。

Gin 模板渲染不是“配个引擎就能用”,而是必须显式加载模板文件后,c.HTML() 才能正确找到并执行渲染——漏掉 LoadHTMLGlob 或 LoadHTMLFiles,直接调 c.HTML() 会 panic 报错 template: "xxx" is undefined。
模板文件必须先加载,否则 c.HTML() 会失败
Gin 不会在运行时自动扫描 templates/ 目录。你得主动告诉它哪些文件要加载、怎么加载:
-
r.LoadHTMLGlob("templates/**/*.tmpl"):推荐用于开发,支持嵌套目录和通配符(如**匹配多级子目录) -
r.LoadHTMLGlob("templates/*"):只匹配一级子目录,templates/users/index.tmpl这类路径不会被加载 -
r.LoadHTMLFiles("templates/layout.html", "templates/home.tmpl"):适合生产环境,加载明确列表,避免误加载测试模板 - 路径必须是相对启动命令所在目录的路径,比如
go run main.go在项目根目录执行,则"templates/*.tmpl"有效;若在子目录执行,需调整为"../templates/*.tmpl"
{{.FieldName}} 只能访问顶层字段,嵌套结构要用点号展开
传入 c.HTML() 的数据是 gin.H(即 map[string]interface{}),但模板里不能直接解构 struct 字段或 map 值:
- ✅ 正确:
{{.Title}}、{{.User.Name}}(User是 struct 或 map)、{{.Items.0}}(切片首项) - ❌ 错误:
{{with .User}}{{.Name}}{{end}}中如果.User是 nil,会 panic;应改用{{if .User}}{{.User.Name}}{{end}} - ⚠️ 注意:
{{.Now.Format "2006-01-02"}}要求.Now是time.Time类型,传字符串会报can't call method Format on string - 函数调用必须带括号:
{{len .Items}},写成{{len .Items}}是对的,但{{len .Items}}少空格或括号都会语法错误
模板复用靠 {{define}} 和 {{template}},不是文件包含
Gin 没有类似 include "header.html" 的语句;复用靠命名模板 + 显式调用:
- 在任意模板中用
{{define "header"}}{{end}}定义局部模板 - 在同个文件或已加载的其他模板中,用
{{template "header" .}}渲染,.表示把当前上下文传进去 - 跨文件复用需确保所有模板都通过
LoadHTMLGlob或LoadHTMLFiles一次性加载——Gin 不支持按需读取单个模板文件 - 定义名区分大小写:
{{define "Header"}}和{{template "header" .}}不匹配
静态资源不走模板系统,要单独配置 r.Static()
模板里的 这类路径,不会被模板引擎处理,必须由 Gin 路由接管:
- 加一行
r.Static("/static", "./static"),才能让/static/路径返回./static/下真实文件 - 路径前缀(第一个参数)必须以
/开头,否则注册失败且无提示 - 不要把静态文件放在
templates/下——LoadHTMLGlob可能误加载 CSS/JS 文件并尝试解析为模板,导致启动失败 - 模板中引用静态资源时,路径写绝对路径(如
/static/js/main.js),别用相对路径(js/main.js),否则路由嵌套时易 404
最容易被忽略的是模板加载时机:它必须在任何 GET/POST 路由注册之前完成。放到 r.GET() 后面,等于没加载。











