
Martini 的 render 包因自定义模板分隔符与模板中实际使用的分隔符不一致,导致 {{ yield }} 未被正确解析和替换,本文详解原因及两种可靠修复方式。
martini 的 render 包因自定义模板分隔符与模板中实际使用的分隔符不一致,导致 `{{ yield }}` 未被正确解析和替换,本文详解原因及两种可靠修复方式。
在使用 Martini 框架配合 martini-contrib/render 进行模板渲染时,layout.html 中的 {{ yield }} 占位符未能被子模板内容替换,而是以纯文本形式直接输出到 HTML 页面中——这是开发者常遇到的典型配置失配问题。
根本原因在于:模板分隔符(delimiters)配置与模板中实际书写的语法不一致。
你当前的 render 配置指定了自定义分隔符:
Delims: render.Delims{"{[{", "}]}"}
这意味着 render 包只会识别形如 {[{ yield }]} 的语法作为有效指令,而你的 layout.html 中却写的是标准 Go 模板语法:
{{ yield }}
由于 {{ 和 }} 不匹配 {[{ 和 }]},render 引擎将 {{ yield }} 视为普通文本,不做任何处理,因此原样输出。
✅ 解决方案一(推荐):统一使用标准分隔符
修改 render 初始化代码,将 Delims 设为默认的 {{ / }}:
m.Use(render.Renderer(render.Options{
Directory: "templates",
Layout: "layout",
Extensions: []string{".tmpl", ".html"},
Delims: render.Delims{"{{", "}}"}, // ← 关键修正
Charset: "UTF-8",
IndentJSON: true,
}))
保持 layout.html 和 index.html 原写法不变,即可正常工作:
<!-- layout.html -->
<title>My App</title><header>Header</header>
{{ yield }} <!-- ✅ 现在会被正确替换 -->
<footer>Footer</footer>
✅ 解决方案二:适配自定义分隔符(适用于需规避 {{ 冲突的场景)
若因前端框架(如 Vue/Handlebars)也使用 {{ 而必须自定义分隔符,则需同步修改所有模板中的指令:
<!-- layout.html -->
<header>Header</header>
{[{ yield }]} <!-- ✅ 与 Delims 配置严格一致 -->
<footer>Footer</footer>
⚠️ 注意事项:
- Delims 必须在 render.Renderer() 初始化时一次性设定,运行时不可更改;
- 所有模板(包括 layout、子模板、partial)均需遵循同一套分隔符规则;
- 若混用多种分隔符(如部分模板用 {{,部分用 {[{),将导致不可预测的渲染行为;
- layout 模板名需与文件名完全一致(不含扩展名),且确保 layout.html 位于 templates/ 目录下。
总结:Martini render 的 yield 机制本身无缺陷,问题几乎总是源于分隔符配置与模板语法的错位。只需确保 Delims 参数与模板中 yield 指令的包裹符号完全一致,即可立即解决内容不注入的问题。










