
在 Go 的 html/template 包中,
这是设计使然:html/template 的核心目标是默认安全,而非完全可控的字符串输出。其源码中 html.go 的 escapeText 函数明确对 contentTypeHTML 上下文执行 ' 和 " 的转义,无法通过用户侧 API 关闭。
✅ 正确解决方案:改用 text/template 并手动转义敏感字符
package main
import (
"strings"
"text/template"
"os"
)
const tmpl = `
{{.Title}}
`
// safeHTML 将输入字符串中可能引发 XSS 的字符转义(仅需转义 <, >, &, ")
func safeHTML(s string) string {
s = strings.ReplaceAll(s, "&", "&")
s = strings.ReplaceAll(s, "<", "zuojiankuohaophpcn")
s = strings.ReplaceAll(s, ">", "youjiankuohaophpcn")
s = strings.ReplaceAll(s, `"`, """)
return s
}
func main() {
t := template.Must(template.New("ex").Funcs(template.FuncMap{
"safe": safeHTML,
}).Parse(tmpl))
v := map[string]interface{}{
"Title": "Hello World'", // 原始字符串,不包装 template.HTML
}
t.Execute(os.Stdout, v)
}⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- 不要试图用 template.HTML + text/template 组合——text/template 不识别该类型,会直接调用 .String() 或 fmt.Sprint,失去语义;
- 若模板中还需渲染其他 HTML 片段(如动态
- 对于完整 HTML 页面生成,更推荐保持 html/template,并通过调整结构规避 RCDATA 限制(例如:将标题内容通过 JavaScript 注入或使用 + CSS 替代
)。
总之,html/template 的 ' 转义不是 bug,而是安全模型的一部分。当业务逻辑明确要求保留原始单引号且可确保上下文无 XSS 风险时,切换至 text/template 并精细化控制转义,才是清晰、可靠、符合 Go 工程实践的选择。











