直接用html/template渲染多行字符串模板是安全的,但必须显式声明内容为template.html类型或使用safehtml函数,否则自动转义;须确保导入html/template而非text/template,且变量值类型决定是否转义。

直接用 html/template 渲染多行字符串模板是安全的,但必须显式声明模板内容为 HTML 类型,否则会自动转义——这是绝大多数人踩坑的根源。
为什么 template.ParseStrings 不行?
Go 标准库没有 ParseStrings 这个方法。常见误操作是试图用 template.New + Parse 直接传入多行字符串,却忽略了模板解析前的类型绑定问题。
-
template.New("t").Parse("{{.Name}}")创建的是纯文本模板,即使内容含 HTML 标签也会被转义 - 多行字符串本身(如反引号包裹)没问题,但模板引擎不因换行而改变输出行为
- 真正起作用的是后续调用时的数据类型和模板函数链,不是字符串格式
正确做法:用 template.Must + template.New 显式指定 FuncMap 并用 template.HTML
关键不是“怎么写多行”,而是“怎么告诉模板:这段内容可信,别转义”。核心路径只有一条:把数据包装成 template.HTML 类型,或在模板里用 safeHTML 函数。
- 在 Go 代码中,将待渲染的 HTML 字符串转为
template.HTML类型再传入:data := struct { Content template.HTML }{ Content: template.HTML(`<h2>标题</h2> <p>段落内容</p>`), } - 若模板内需动态拼接,定义自定义函数:
funcMap := template.FuncMap{ "safeHTML": func(s string) template.HTML { return template.HTML(s) }, } t := template.Must(template.New("page").Funcs(funcMap).Parse(`{{.Content | safeHTML}}`)) - 别用
{{.Content | html}}—— 这是反向操作,会二次转义
常见错误:混用 text/template 和 html/template
两者 API 几乎一致,但底层校验逻辑完全不同。text/template 对 HTML 完全无感知,html/template 会做上下文敏感转义。一旦用错包,多行模板照常运行,但 XSS 风险就藏进去了。
- 确保 import 是
"html/template",不是"text/template" - 检查所有
template.New调用是否来自html/template包(IDE 悬停看类型) - 如果模板里用了
{{.UserInput}}且未包装成template.HTML,它一定会被转义成 <script> —— 这是设计使然,不是 bug
最易忽略的一点:模板变量名本身不影响转义行为,决定是否转义的只有值的类型(string vs template.HTML)和模板所属包(html/template)。哪怕你写十行缩进、带注释的模板字符串,只要值是普通 string,照样转义。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











