
Go 模板默认会对变量进行 HTML 转义以防止 XSS,若需插入可信的原始 HTML 或 JSON 字符串,须显式使用 template.HTML 类型或 template.JS 类型包装数据,避免自动转义破坏结构。
go 模板默认会对变量进行 html 转义以防止 xss,若需插入可信的原始 html 或 json 字符串,须显式使用 `template.html` 类型或 `template.js` 类型包装数据,避免自动转义破坏结构。
在 Go 的 html/template 包中,所有通过 {{.FieldName}} 插入的字符串默认被视为需要转义的纯文本——这是安全优先的设计: 变成 <code><," 变成 ",> 变成 >,以此防范跨站脚本(XSS)攻击。但当你明确知道某段内容是已校验、可信的 HTML 片段(如后台生成的富文本),或需原样注入 JSON 数据到 <script></script> 标签中时,必须绕过默认转义机制。
核心解决方案是:使用模板预定义的安全类型包装原始内容:
-
template.HTML:用于插入未经转义的 HTML 字符串; -
template.JS:用于插入未经转义的 JavaScript/JSON 字符串(自动处理引号与反斜杠); -
template.URL、template.CSS等:适用于对应上下文,确保语义安全。
✅ 正确做法示例:
package main
import (
"html/template"
"os"
)
func main() {
const tmplStr = `
{{define "page"}}
<div class="content">
{{.RawHTML}} <!-- ✅ template.HTML → 原样渲染 -->
{{.RawJSON}} <!-- ✅ template.JS → 保持 JSON 结构 -->
</div>
<script>
const data = {{.RawJSON}}; // 直接作为 JS 对象使用
console.log(data.title);
</script>
{{end}}`
t := template.Must(template.New("page").Parse(tmplStr))
data := map[string]interface{}{
"RawHTML": template.HTML(`<p class="highlight">Hello <strong>World</strong>!</p>`),
"RawJSON": template.JS(`{"title":"Go Template","version":1.23}`),
}
t.ExecuteTemplate(os.Stdout, "page", data)
}⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
-
切勿对用户输入直接使用
template.HTML—— 这会彻底关闭 XSS 防护,仅限完全可信、服务端可控的内容; - 若 HTML 来自数据库或 CMS,请先通过
bluemonday或golang.org/x/net/html等库进行白名单净化后再封装; - JSON 插入务必用
template.JS而非string,否则双引号会被转义为",导致 JS 解析失败; - 不要尝试用
{{.Field | safeHTML}}(该函数不存在),Go 模板不提供“取消转义”的过滤器——安全模型基于类型驱动,而非运行时指令。
总结:Go 模板的“自动转义”不是限制,而是保障。真正需要插入原始内容时,只需将数据显式转换为 template.HTML 或 template.JS 类型即可——既保持安全性边界,又满足灵活渲染需求。



















