c.html默认不支持多布局切换,因其底层仅调用一次engine.htmlrender,而gin内置渲染器只注册单个根模板目录和一套主模板,无原生layout slot或继承机制,传入模板被当作完整html直接渲染,不会自动套壳。

为什么 c.HTML 默认不支持多布局切换
因为 c.HTML 底层只调用一次 engine.HTMLRender 渲染器,而 Gin 内置的 HTMLRender(如 gin.Default() 自带的)只注册一个根模板目录和一套主模板,没有内置“layout slot”或“继承机制”。你传进去的模板文件被当作完整 HTML 渲染,不会自动套壳。
手动实现不同路由用不同布局的两种可靠方式
核心思路:不依赖框架自动 layout,而是自己组织模板嵌套,并在每个路由中显式指定主模板路径。Gin 支持 {{template "xxx" .}} 和 {{define "xxx"}},只要提前 LoadHTMLGlob 或 LoadHTMLFiles 加载了所有相关文件即可。
- 把公共结构(如
、导航栏、页脚)抽成独立子模板,比如layouts/base.html、layouts/admin.html、layouts/public.html - 每个页面模板(如
pages/home.html、pages/dashboard.html)用{{define "content"}}包裹主体,然后在对应 layout 中用{{template "content" .}}插入 - 在路由 handler 里,根据业务逻辑决定用哪个 layout 模板名来调用
c.HTML,例如:c.HTML(200, "layouts/admin.html", data)或c.HTML(200, "layouts/public.html", data)
LoadHTMLGlob 路径匹配要注意的坑
模板加载顺序和路径通配范围直接影响 {{template}} 是否能被识别。常见错误是子模板没被加载,导致运行时报 template: "xxx" is undefined。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 必须确保
base.html、admin.html、public.html都在LoadHTMLGlob("templates/**/*")覆盖范围内;推荐用LoadHTMLGlob("templates/*.html")+LoadHTMLGlob("templates/layouts/*.html")+LoadHTMLGlob("templates/pages/*.html")分多次显式加载,避免遗漏 - 不要用相对路径如
"./templates/...",启动时工作目录不确定;改用绝对路径或基于os.Executable()推导 -
{{template "header" .}}中的名称必须和{{define "header"}}完全一致,大小写敏感,且不能含斜杠
路由 handler 中如何动态选 layout
没有全局 layout 配置,所以选哪个 layout 是纯业务判断——取决于用户角色、请求路径、参数甚至 AB 测试标识。别试图抽象成中间件统一处理,容易失控。
- 简单场景:用
c.Request.URL.Path做前缀判断,比如/admin/*→"layouts/admin.html",其余 →"layouts/public.html" - 权限相关:先执行鉴权逻辑(如检查
c.Get("user_role")),再决定 layout,避免未授权用户看到 admin 布局的 DOM 结构 - 避免硬编码模板名,可封装为 map:
layoutMap := map[string]string{"user": "layouts/user.html", "admin": "layouts/admin.html"},然后c.HTML(200, layoutMap[role], data)
真正麻烦的不是怎么写模板嵌套,而是确保所有 {{define}} 名称全局唯一、加载时机早于任何 c.HTML 调用、以及每次渲染都传入 layout 所需的全部上下文字段(比如 IsAdmin 这种布尔值常被漏传)。这些细节一旦出错,页面要么空白,要么报 template error,但错误信息往往不指明哪行模板出了问题。










