跳到主要内容

模板渲染

问题

Go 中如何使用模板引擎进行服务端渲染?

答案

html/template 标准库

// 基础模板
tmpl := template.Must(template.ParseFiles("templates/index.html"))

func handler(w http.ResponseWriter, r *http.Request) {
data := struct {
Title string
Items []string
}{
Title: "商品列表",
Items: []string{"Go 编程", "Redis 实战"},
}
tmpl.Execute(w, data)
}
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head><title>{{.Title}}</title></head>
<body>
<h1>{{.Title}}</h1>
<ul>
{{range .Items}}
<li>{{.}}</li>
{{end}}
</ul>
</body>
</html>

模板语法

语法说明示例
{{.Field}}访问字段{{.Name}}
{{range}}循环{{range .Items}}...{{end}}
{{if}}条件{{if .IsAdmin}}...{{end}}
{{template}}引入子模板{{template "header" .}}
{{block}}可覆盖块{{block "content" .}}默认{{end}}
{{with}}切换上下文{{with .User}}{{.Name}}{{end}}
|管道{{.Date | formatDate}}

Gin 模板渲染

r := gin.Default()

// 加载模板
r.LoadHTMLGlob("templates/**/*")
// 或
r.LoadHTMLFiles("templates/index.html", "templates/about.html")

// 自定义模板函数
r.SetFuncMap(template.FuncMap{
"formatDate": func(t time.Time) string {
return t.Format("2006-01-02")
},
"upper": strings.ToUpper,
})

r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{
"title": "首页",
"items": items,
})
})

模板布局(继承)

<!-- templates/base.html -->
{{define "base"}}
<!DOCTYPE html>
<html>
<head><title>{{block "title" .}}默认标题{{end}}</title></head>
<body>
{{template "nav" .}}
<main>{{block "content" .}}{{end}}</main>
{{template "footer" .}}
</body>
</html>
{{end}}

<!-- templates/home.html -->
{{template "base" .}}
{{define "title"}}首页{{end}}
{{define "content"}}
<h1>欢迎</h1>
{{end}}
XSS 防护

html/template 自动转义 HTML 特殊字符,默认安全。如果确实需要输出原始 HTML,使用 template.HTML 类型:

data := struct {
SafeHTML template.HTML
}{
SafeHTML: template.HTML("<b>加粗</b>"), // 不转义
}

只在信任的内容上使用 template.HTML,否则会引入 XSS。


常见面试问题

Q1: text/templatehtml/template 的区别?

答案

  • html/template:自动 HTML 转义,防 XSS,用于 Web 页面
  • text/template:不转义,用于生成代码、配置文件等纯文本

API 完全相同,Web 场景必须用 html/template

Q2: Go 模板引擎适合做前后端一体吗?

答案:适合简单页面(管理后台、邮件模板),不适合复杂交互应用。Go 社区的主流做法是:

  • 前后端分离:Go 做 API,前端用 React/Vue
  • HTMX:轻量级方案,用 Go 模板 + HTMX 做局部更新

相关链接