gin模板默认对变量html转义,需用{{ .rawhtml | safehtml }}输出可信html、{{ printf "%s" .rawstring }}原样输出特殊符号字符串,或{{ ... }}写静态原始字面量。

Gin 模板默认会对变量内容做 HTML 转义(比如 、<code>>、&),所以直接写 {{ .rawHTML }} 会把本意是渲染的 HTML 标签变成纯文本。要原样输出大段含特殊符号(如 HTML 标签、JSON 字符串、代码块、转义序列)的内容,关键不是“禁用转义”,而是**选对模板语法和数据类型**。
用 {{ .rawHTML | safeHTML }} 渲染已信任的 HTML 字符串
这是最常见也最容易踩坑的场景:后端拼好了一段 HTML 片段(比如富文本编辑器存的内容),想在模板里直接插入 DOM。
-
safeHTML是 Gin 内置的模板函数,它告诉模板引擎“这段字符串已清洗过,可跳过 HTML 转义” - 必须确保传入的是
string类型;如果传nil或非字符串类型(如map、struct),运行时会 panic 报错can't evaluate field safeHTML - 不要在未校验来源时滥用——用户输入的 HTML 直接套
| safeHTML会导致 XSS
示例:
{{ .articleContent | safeHTML }}
对应后端传值:c.HTML(200, "post.tmpl", gin.H{"articleContent": "<p>Hello <strong>world</strong></p>"})
用 {{ printf "%s" .rawString }} 避免自动转义任意字符串
当内容不是 HTML,而是带大量 、<code>>、{、}、$、反斜杠等符号的纯文本(比如 JSON 示例、Go 代码片段、正则表达式),safeHTML 不适用——它只针对 HTML 解析上下文,且仍会处理实体编码。
-
printf "%s"是 Go 模板原生函数,绕过所有模板转义逻辑,原样输出字符串字面量 - 适用于日志 dump、配置示例、错误堆栈、SQL 片段等需要“所见即所得”的场景
- 注意:如果字符串本身含未转义的双引号或换行,可能破坏 HTML 结构;建议配合
<pre class="brush:php;toolbar:false;"><code></code> 使用</pre>
示例:
<pre class="brush:php;toolbar:false;"><code>{{ printf "%s" .exampleCode }}</code>
后端传值:c.HTML(200, "doc.tmpl", gin.H{"exampleCode": "func hello() {\n\tfmt.Println(\"$HOME\")\n}"})
模板里写原始字符串字面量:用 {{ `...` }} 包裹静态内容
如果那“大段特殊符号”是固定不变的(比如文档里的 JSON 模板、HTTP 请求示例),根本不需要从后端传,直接在模板里写更安全、更轻量。
- Go 模板支持反引号包裹的原始字符串字面量:
{{ `{"name": "a", "id": 1}` }},内部所有字符(包括换行、\t、\n、$)都不解析、不转义 - 不能插值——
{{ `hello {{.Name}}` }}会原样输出hello {{.Name}},不是你想要的 - 适合写文档页、调试页、API 响应示例等静态内容
示例:
请求体示例:
{{ `{
"query": "site:example.com",
"page": 1,
"per_page": 10
}` }}
为什么 {{ .raw | html }} 或 {{ .raw | js }} 多数时候不对路
Go 标准库模板有 html、js、urlquery 等安全函数,但它们不是“取消转义”,而是“按目标上下文重新转义”。
-
{{ .x | html }}会把变成 <code><,再变一次转义,结果更乱 -
{{ .x | js }}是为嵌入<script></script>准备的,会对单双引号、反斜杠加转义,不适合展示代码 - Gin 默认没注册这些函数(除非你自己
Funcs注册),直接用会报function "html" not defined
真正需要“原样输出”,就别碰这些上下文敏感函数——回到 printf "%s" 或原始字面量。
最容易被忽略的一点:Gin 的 LoadHTMLFiles 或 LoadHTMLGlob 加载模板时,如果文件本身含 UTF-8 BOM 或混合了 Windows/Linux 换行符(\r\n vs \n),可能导致模板解析失败或空格错位。遇到“明明写了 {{ `...` }} 却还是被截断”的情况,先用 file -i templates/*.tmpl 查编码,再用 dos2unix 统一换行符。











