html/template默认自动转义防xss,text/template不转义仅作纯文本输出;需用template.html包装可信html字符串,且必须配合白名单过滤等安全措施。

为什么直接用 fmt.Sprintf 拼接 HTML 很危险
因为 fmt.Sprintf 不做任何转义,变量里只要含 <script></script> 或 " 就可能触发 XSS。模板引擎的核心价值不是“更方便”,而是“默认安全”。text/template 在渲染时自动对 HTML 特殊字符做转义,前提是变量必须通过 {{.Name}} 这种语法插入,而不是拼接字符串。
如何让 template 正确渲染 HTML 字符串而不转义
有时你确实需要输出原始 HTML(比如富文本内容),但 text/template 默认会把 <b>hello</b> 渲染成文字。这时不能用 html/template——它专为 HTML 场景设计,且默认更严格;而 text/template 本身不提供 template.HTML 类型支持。正确做法是:换用 html/template,并用 template.HTML 类型包裹值。
- 定义结构体字段为
template.HTML类型,而非string - 在模板中仍用
{{.Content}},不会被转义 - 注意:仅当数据来源可信时才这么做,否则仍是 XSS 风险入口
如何传入变量并避免常见 panic
常见错误是传 nil 指针或未导出字段,导致 template: …: nil pointer evaluating … 或 cannot evaluate field …。关键点有三个:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 结构体字段名必须大写(首字母导出),否则模板无法访问
- 传入
Execute的数据必须是地址(如&data),尤其当模板内用指针接收方法时 - 用
with或if做空值判断,例如{{if .User.Name}}{{.User.Name}}{{else}}匿名{{end}}
如何复用模板片段(如 header / footer)
用 template 动作加载子模板,但要注意路径和定义顺序:
- 子模板必须先
define后template,否则报template: …: "xxx" is not defined - 推荐把所有
define放在一个顶层文件里,再用ParseFiles一次性加载 - 如果子模板需要局部变量,用
{{template "name" .}}传当前上下文,或{{template "name" $item}}传特定值
最易被忽略的是模板执行时的上下文绑定时机——Execute 调用那一刻才真正解析变量,所以修改结构体字段后必须重新执行,不能指望模板“自动响应”。另外,text/template 不支持嵌套作用域变量声明(比如 {{ $x := "test" }} 只在当前 action 块有效),跨块要用 with 或提前组织好数据结构。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










