
Go 模板默认会转义 HTML 特殊字符(包括 ),导致原始字符串中的 \n 无法在浏览器中显示为换行;需通过预处理将换行符替换为安全的 标签,或使用 template.HTML 类型配合自定义函数实现安全、可复用的换行渲染。
go 模板默认会转义 html 特殊字符(包括 `
`),导致原始字符串中的 `\n` 无法在浏览器中显示为换行;需通过预处理将换行符替换为安全的 `
` 标签,或使用 `template.html` 类型配合自定义函数实现安全、可复用的换行渲染。
在 Go 的 html/template 包中,所有通过 {{.Field}} 插入的变量值都会被自动 HTML 转义(如 ),这是防止 XSS 攻击的安全机制。因此,即使你的数据中包含 \n,浏览器接收到的仍是纯文本换行符,而 HTML 会忽略它(HTML 中连续空白符(含换行)默认折叠为单个空格)。
✅ 正确做法:安全地将 \n 渲染为
方法一:模板外预处理(简单直接)
在传入模板前,将换行符替换为
,并显式标记为 template.HTML 类型:
import "html/template"
type PageData struct {
Content template.HTML // 注意类型!
}
func handler(w http.ResponseWriter, r *http.Request) {
raw := "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.google.com"
// 安全替换:仅替换 \n,不引入额外 HTML 注入风险
safeHTML := template.HTML(strings.ReplaceAll(raw, "\n", "<br>\n"))
data := PageData{Content: safeHTML}
t := template.Must(template.New("page").Parse(`
<tr>
<td>TextBody</td>
<td>{{.Content}}</td>
</tr>
`))
t.Execute(w, data)
}
⚠️ 注意:必须使用 template.HTML 类型,否则 {{.Content}} 仍会被转义;strings.ReplaceAll 是安全的,因它不解析用户输入中的 HTML 标签。
方法二:注册自定义模板函数(推荐,复用性强)
在模板中定义可重用的 nl2br 函数:
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
func nl2br(s string) template.HTML {
return template.HTML(strings.ReplaceAll(s, "\n", "<br>"))
}
t := template.Must(template.New("page").
Funcs(template.FuncMap{"nl2br": nl2br}).
Parse(`{{.Content | nl2br}}`))
然后在模板中调用:
<td>{{.Content | nl2br}}</td>
方法三:CSS 方案(纯前端,无需后端修改)
若内容语义上是纯文本(无富文本需求),更简洁的方式是用 CSS 保留换行:
<td style="white-space: pre-line;">{{.Content}}</td>
✅ white-space: pre-line 会:
- 保留 \n 作为换行符;
- 合并多余空格;
- 自动换行以适应容器宽度;
- 无需 HTML 转义风险,最安全轻量。
❌ 错误示例(避免)
// 危险!直接注入未转义 HTML(可能引发 XSS) body = strings.Replace(body, "\n", "<br>", -1) // ❌ 在模板渲染后操作 HTML 字符串 fmt.Fprint(w, body) // 若原始内容含 <script>,将被执行!</script>
此方式绕过模板安全机制,属于反模式,绝对禁止。
总结
- Go 模板的 \n 不会自动转为
,这是设计使然(安全优先); - 推荐优先使用 white-space: pre-line CSS 方案,零侵入、零风险;
- 若需
语义(如邮件模板、兼容旧样式),请使用 template.HTML + 预处理 或 自定义 nl2br 函数; - 切勿在 template.Execute 后手动字符串替换 HTML 输出——这破坏了模板的 XSS 防护能力。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










