c.HTML是Gin中唯一渲染HTML模板的方法,必须在r.Run()前用LoadHTMLGlob或LoadHTMLFiles预加载模板,否则panic;参数为c.HTML(statusCode, name, obj),name需与加载路径一致,obj推荐gin.H。

c.HTML 是 Gin 框架中唯一用于渲染 HTML 模板的响应方法,它必须配合提前加载的模板使用,否则会 panic。
模板必须先加载,c.HTML 才能工作
Gin 不会在运行时动态读取模板文件,所有模板必须在 r.Run() 之前通过 LoadHTMLGlob 或 LoadHTMLFiles 加载进内存。没加载就调 c.HTML,会直接报错:template: "xxx.html" is undefined。
-
r.LoadHTMLGlob("templates/**/*")最常用:递归匹配所有子目录下的 HTML/TMPL 文件 -
r.LoadHTMLFiles("templates/index.html", "templates/user/list.tmpl")适合明确知道文件列表的场景,不支持通配符 - 路径是相对
os.Getwd()(启动命令所在目录)的,不是相对于main.go;用./templates/...更稳妥 - 加载后模板名就是文件系统中的路径(不含
templates/前缀),比如templates/posts/show.tmpl→ 渲染时传"posts/show.tmpl"
c.HTML 的参数顺序和数据结构
签名是 c.HTML(statusCode int, name string, obj interface{}),三个参数缺一不可:
-
statusCode:必须是 HTTP 状态码,如200、404,不能省略或写成字符串 -
name:模板文件名(含路径和扩展名),必须与LoadHTMLGlob匹配到的路径完全一致 -
obj:传入的数据,推荐用gin.H{"key": value}(即map[string]interface{}),避免结构体字段未导出导致渲染为空
错误示例:c.HTML(200, "index.html", {"title": "Home"}) —— Go 里没有字面量 map,会编译失败。
常见转义问题:JS/CSS/HTML 内容被自动编码
默认情况下,{{.Content}} 中的 HTML 标签会被转义成文本(如 <script></script>),这是 html/template 的安全机制。需要原样输出时:
- 用
{{.Content | safeHTML}},前提是Content是template.HTML类型 - 或在 Go 层转换:
gin.H{"Content": template.HTML(rawString)} - 不要用
{{.Content | safe}}——safe不是标准函数,会报template: "xxx" is not a defined function - 自定义函数需通过
template.FuncMap注册,且必须在LoadHTMLGlob之前完成
嵌套模板和继承需手动处理,Gin 不额外封装
Gin 只做模板加载和 c.HTML 调用,{{define}}、{{template}}、{{block}} 等语法完全由 Go 标准库 html/template 支持,Gin 不介入解析逻辑。
- 基础模板(如
layout.html)和子模板(如home.html)都得放进LoadHTMLGlob路径下 - 子模板里写
{{template "layout.html" .}}或{{define "main"}}...{{end}}都可以,但名字必须严格匹配 - 如果子模板用了
{{template "sidebar" .}}却没定义sidebar,运行时 panic,错误信息不提示具体哪行,只报template: ...: "sidebar" is not defined
真正容易被忽略的是:模板继承依赖于 template.ParseFiles 的内部缓存行为,一旦你用 r.SetHTMLTemplate 替换默认引擎,又没把全部模板文件传进去,就会出现部分模板“突然找不到”的情况。


















