Go 模板默认仅转义 <, >, &, ', " 五个 HTML 危险字符,而 Unicode 字符(如德文变音字母)无需转义,只需确保 HTML 响应声明 UTF-8 编码即可正常显示。
go 模板默认仅转义 ``, `&`, `'`, `"` 五个 html 危险字符,而 unicode 字符(如德文变音字母)无需转义,只需确保 html 响应声明 utf-8 编码即可正常显示。
Go 的 html/template 包设计遵循安全优先原则:它自动对可能引发 XSS 的 HTML 元字符进行转义(即调用 html.EscapeString),但不会也不应转义合法的 UTF-8 文本字符(如 ä, å, ü, ö, ß, 中文、日文等)。这些字符本身是 HTML 和现代浏览器原生支持的——前提是文档明确声明了正确的字符编码。
✅ 正确做法是:保持 Go 模板中的原始 UTF-8 字符不变,仅在 HTML 输出中声明 charset=utf-8。
例如,模板文件 index.html 应包含标准的 UTF-8 声明:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- 或更推荐的 HTML5 写法 -->
<!-- <meta charset="utf-8"> -->
<title>Go Template with UTF-8</title>
</head>
<body>
{{define "T"}}特殊字符:{{.}}{{end}}
</body>
</html>Go 服务端代码保持简洁,无需手动转义:
package main
import (
"log"
"os"
"text/template"
)
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
func main() {
t, err := template.New("page").Parse(`<!DOCTYPE html>
<html><head><meta charset="utf-8"></head>
<body>{{define "T"}}特殊字符:{{.}}{{end}}</body></html>`)
check(err)
// 直接传入 UTF-8 字符串(Go 源文件需保存为 UTF-8 编码)
err = t.ExecuteTemplate(os.Stdout, "T", "<>&' äåüöß")
check(err)
}输出将正确呈现为:
<!DOCTYPE html> <html><head><meta charset="utf-8"></head> <body>特殊字符:<>&' äåüöß</body></html>
其中 äåüöß 以原始 UTF-8 字节形式存在,浏览器根据 <meta charset="utf-8"> 正确解码并渲染。
⚠️ 注意事项:
- 切勿手动 HTML 转义 Unicode 字符(如将 ä 替换为 ä 或 ä):Go 模板会二次转义 &,导致 ä,最终显示为文字而非字符。
- 确保 .go 源文件本身以 UTF-8 编码保存(绝大多数编辑器默认支持)。
- HTTP 响应头也应显式设置 Content-Type: text/html; charset=utf-8(net/http 默认已设置,但自定义响应时需注意):
w.Header().Set("Content-Type", "text/html; charset=utf-8") - 若通过 template.HTML 类型绕过转义,请仅用于完全可信的 HTML 片段,绝不用于动态文本,否则破坏安全模型。
总结:Go 模板对国际化文本的支持是开箱即用的——你不需要做任何额外转义;真正关键的是统一且显式地声明 UTF-8 编码(HTML <meta> + HTTP 头),这是现代 Web 渲染多语言内容的基石。

















