模板渲染
问题
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/template 和 html/template 的区别?
答案:
html/template:自动 HTML 转义,防 XSS,用于 Web 页面text/template:不转义,用于生成代码、配置文件等纯文本
API 完全相同,Web 场景必须用 html/template。
Q2: Go 模板引擎适合做前后端一体吗?
答案:适合简单页面(管理后台、邮件模板),不适合复杂交互应用。Go 社区的主流做法是:
- 前后端分离:Go 做 API,前端用 React/Vue
- HTMX:轻量级方案,用 Go 模板 + HTMX 做局部更新