html/template 默认自动转义html特殊字符,需确认导入路径正确、避免误用text/template或手动转template.html;仅对可信html内容用template.html类型传递。

html/template 默认就转义,别误用 text/template
只要导入的是 html/template(不是 text/template),所有 {{.Field}} 插值都会自动转义 HTML 特殊字符: → <code>,<code>> → >,& → &," → ",' → '。这不是可选项,是默认行为。
常见错误现象:template.Execute 输出的页面里,用户输入的 <script>alert(1)</script> 显示为纯文本——这恰恰说明防护生效了;如果它真执行了,大概率是你 import 了 text/template,或变量被手动包装成 template.HTML。
- 确认导入路径是
"html/template",不是"text/template" - 检查模板文件是否被
template.ParseFiles加载时混用了两个包 - 避免在 handler 中把用户数据强制转成
template.HTML,这是主动开后门
绕过转义必须用 template.HTML 类型,不是函数或 filter
想让一段已知可信的 HTML(比如后台编辑的公告)原样渲染,唯一合法方式是在 Go 代码中把它转成 template.HTML 类型。模板里仍写 {{.Content}},不加任何管道符或函数。
常见错误现象:{{.Content | safeHTML}} 不生效(safeHTML 是 Go 1.12+ 已弃用的旧写法);{{printf "%s" .Content}} 或 strings.Replace 拼接后传入,依然会被转义——因为模板只识别 template.HTML 这个空 struct 类型。
- 正确做法:
data.Content = template.HTML(rawHTML),再传给模板 -
template.HTML零值是空字符串,不能用nil初始化 - 绝不能对用户输入、API 返回内容、表单字段调用
template.HTML
属性、JS、URL 等上下文要匹配对应类型
html/template 不是全局替换 ,而是根据插入位置动态选择策略:写进 <code>href="" 会 URL 编码,塞进 onclick="" 会 JS 字符串转义,放进 style="" 会 CSS 转义。但前提是它能准确识别上下文。
常见错误现象:写成 <a href="https://www.php.cn/link/8627a5992a7f67f8c1e3db85cf9c23eb">link</a>(没引号),导致 .URL 含空格或 " 时破坏 HTML 结构;或者把 JSON 直接 {{.Config}} 塞进 <script></script>,引发 JS 语法错误。
- HTML 属性值必须用双引号包裹:
href="https://www.php.cn/link/8627a5992a7f67f8c1e3db85cf9c23eb" - URL 类型变量应包装为
template.URL,或确保协议白名单校验(如只允许https://) - JS 字符串用
template.JS包装,CSS 用template.CSS - 嵌入 JSON 数据时,用
{{.Data|json}}(需注册json函数)
生成 XML/JSON 等非 HTML 内容时别用 html/template
html/template 的转义逻辑专为 HTML 设计,强行用于 XML 会导致 <?xml ...?> 被转成 <?xml ...?>,XML 解析器直接拒收。
常见错误现象:用 html/template.ParseFiles("sitemap.xml") 渲染 Sitemap,返回的 XML 文件无法被搜索引擎解析。
- 纯文本/JSON/XML 场景一律改用
text/template - 更推荐放弃模板,直接用
encoding/xml或encoding/json序列化结构体——类型安全、无注入风险、无需手动转义 - 若必须用
text/template,所有用户输入字段需自行校验和清理(如 URL 格式、XML 字符白名单)
真正容易被忽略的点在于上下文识别的边界:引号缺失、未声明类型、混用包路径,这些细节能让整个自动防护失效。安全不是“用了 html/template 就万事大吉”,而是每处插值都在回答“这个值出现在哪?它该被怎么转义?”
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











