如何在Golang中进行模板渲染_Golang text/template与html/template方法

根本区别在于自动转义行为:html/template默认对插值做HTML实体转义,text/template完全不转义;渲染HTML必须用html/template,纯文本场景用text/template。

text/template 和 html/template 的核心区别在哪

根本区别不在语法,而在自动转义行为:html/template 默认对所有 .Value 插值做 HTML 实体转义(如 zuojiankuohaophpcn),text/template 完全不转义。选错会导致 XSS 漏洞或页面显示乱码。

  • 渲染纯文本日志、邮件正文、配置生成等场景,用 text/template
  • 渲染 HTML 页面、内联 JS/CSS 片段、响应前端的 HTML 内容,必须用 html/template
  • 两者 API 几乎一致,template.ParseFilestmpl.Execute 等调用方式完全相同

如何安全地在 html/template 中插入原始 HTML

直接写 {{.HTMLContent}} 会被转义成一堆 zuojiankuohaophpcndivyoujiankuohaophpcn —— 这不是 bug,是默认防护。要绕过转义,必须显式声明该值“已可信”:

func main() {
	tmpl := template.Must(template.New("").Parse(`{{.SafeHTML}}`))
	data := struct{ SafeHTML template.HTML }{
		SafeHTML: template.HTML(`hello`),
	}
	tmpl.Execute(os.Stdout, data)
}
  • 只能用 template.HTML 类型包裹字符串,不能用 string 强转
  • template.JStemplate.CSStemplate.URL 同理,用于对应上下文的安全注入
  • 切勿把用户输入直接转成 template.HTML,这等于主动关闭 XSS 防护

模板中调用函数和方法要注意什么

两者都支持自定义函数和接收者方法,但函数注册逻辑一致,而方法调用受接收者类型限制:

func sayHi(name string) string { return "Hi, " + name }
tmpl := template.Must(template.New("t").Funcs(template.FuncMap{"hi": sayHi}))
tmpl.Parse(

`{{hi .Name}}`) // ✅ 正确
  • 函数名不能含点号(.),否则 Funcs 会 panic
  • 结构体方法必须是导出(首字母大写),且接收者需为指针或值类型(不能是接口)
  • html/template 中,函数返回值若为 string 仍会被转义;只有返回 template.HTML 等特殊类型才跳过转义

常见 panic 错误:template: xxx: unexpected “.” in operand

多因模板语法写错,比如漏掉空格、括号不匹配,或在 {{if}} 条件里用了非法表达式:

  • {{if .User.Name == ""}} ✅ 合法(Go 模板支持简单比较)
  • {{if .User.Name == nil}} ❌ panic(nil 不可比较,改用 {{if not .User.Name}}
  • {{range .Items}}{{.Name}{{end}} ❌ 缺少右括号,报错位置常指向开头的 .
  • 调试技巧:用 template.Must 包裹 Parse,让错误在加载时暴露,而非执行时静默失败

最易被忽略的是:同一个 *template.Template 实例不能并发调用 Execute,必须为每次请求克隆一份(tmpl.Clone())或创建新实例——否则可能 panic 或输出错乱。