侧边栏模板应命名为sidebar.html并置于templates根目录下,以{{define "sidebar"}}开头;渲染时在主模板中用{{template "sidebar" .}}引入;需通过中间件预置CurrentUser等全局数据;修改后需重启服务并确保LoadHTMLFiles显式加载该文件。

侧边栏模板文件怎么命名和放哪
Gin 默认只认 templates 目录下的 HTML 文件,且不自动递归子目录。侧边栏要复用,必须单独建一个模板文件,比如叫 sidebar.html,放在 templates 根目录下(不是 templates/admin/ 里),否则 {{template "sidebar" .}} 会报 template: "sidebar" is undefined。
常见错误是把 sidebar.html 放在 templates/layout/ 下,然后在主模板里写 {{template "layout/sidebar" .}} ——Gin 不支持斜杠路径引用子模板,只支持扁平命名空间。
正确做法:
-
templates/sidebar.html文件必须以{{define "sidebar"}}开头 - 内容里不能有
{{template ...}}循环引用自己 - 如果依赖当前上下文的字段(比如
.CurrentUser.Role),确保调用方传入的数据结构包含这些字段
c.HTML 渲染时怎么嵌入 sidebar 模板
Gin 的 c.HTML 不支持直接传多个模板名,所以不能靠“多模板叠加”实现布局拆分。必须用 Go 模板原生的 {{template}} 语法,在主模板里显式引入。
例如,templates/admin/index.html 这样写:
{{define "admin/index"}}
<html>
<body>
<div class="layout">
<aside>{{template "sidebar" .}}</aside>
<main>{{.Content}}</main>
</div>
</body>
</html>
{{end}}
注意两点:
-
{{template "sidebar" .}}的第二个参数是当前上下文(.),不是.SidebarData——除非你手动构造了那个字段 - 如果
sidebar.html里用了{{if .CurrentUser.IsAdmin}},而你调用c.HTML(200, "admin/index.html", data)时传的data没有CurrentUser字段,页面就静默失败(不会报错,只是条件不成立)
如何避免每个 handler 都重复传 sidebar 所需数据
侧边栏通常依赖用户登录态、权限、菜单列表等全局数据,不可能每次都在 handler 里手动塞进 gin.H。最稳的方式是用中间件预填充上下文。
写一个中间件:
func InjectSidebarData() gin.HandlerFunc {
return func(c *gin.Context) {
user := c.MustGet("user").(*model.User)
menuItems := getAdminMenuByRole(user.Role)
c.Set("SidebarMenu", menuItems)
c.Set("CurrentUser", user)
c.Next()
}
}
然后在路由注册时挂上:
adminGroup := r.Group("/admin")
adminGroup.Use(InjectSidebarData())
adminGroup.GET("/dashboard", dashboardHandler)
adminGroup.GET("/users", usersHandler)
这样所有 /admin/* 下的 handler 渲染模板时,.SidebarMenu 和 .CurrentUser 就天然可用,sidebar.html 里直接写 {{range .SidebarMenu}} 就行。
为什么 sidebar.html 修改后浏览器没更新
Gin 在开发模式下默认会重新加载模板,但有两个坑容易卡住:
- 修改了
sidebar.html,但没重启服务——Gin 不监听文件变化,改完必须手动重启 - 浏览器缓存了旧的 HTML 响应,尤其是用了
Cache-Control: public, max-age=3600的反向代理(比如 Nginx)——加个时间戳参数或禁用缓存头更可靠 - 模板里用了
{{template "sidebar" .}},但sidebar.html文件本身没被LoadHTMLGlob或LoadHTMLFiles加载过——检查初始化代码是否漏掉了它
最保险的初始化写法是:
r := gin.Default() r.LoadHTMLFiles( "templates/base.html", "templates/sidebar.html", "templates/admin/index.html", "templates/admin/users.html", )
别图省事用 LoadHTMLGlob("templates/**/*"),Gin 对 glob 支持不稳定,某些版本会漏掉深层嵌套的文件。


















