模板基础 #
一、模板概述 #
1.1 什么是模板 #
模板是将动态数据嵌入到静态HTML中的技术:
text
HTML模板 + 数据 → 渲染后的HTML页面
1.2 Gin模板引擎 #
Gin使用Go标准库的 html/template 作为模板引擎:
go
import "html/template"
1.3 模板相关方法 #
| 方法 | 说明 |
|---|---|
| LoadHTMLGlob | 加载单个模式匹配的模板 |
| LoadHTMLFiles | 加载指定文件列表 |
| SetFuncMap | 设置模板函数 |
| HTML | 渲染HTML响应 |
二、加载模板 #
2.1 LoadHTMLGlob #
go
func main() {
r := gin.Default()
// 加载单个目录下所有模板
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{
"title": "首页",
})
})
r.Run()
}
2.2 多级目录加载 #
go
func main() {
r := gin.Default()
// 加载多级目录模板
r.LoadHTMLGlob("templates/**/*")
r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{})
})
r.GET("/user/profile", func(c *gin.Context) {
c.HTML(200, "user/profile.html", gin.H{})
})
r.Run()
}
2.3 LoadHTMLFiles #
go
func main() {
r := gin.Default()
// 加载指定文件
r.LoadHTMLFiles(
"templates/index.html",
"templates/about.html",
)
r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{})
})
r.Run()
}
三、渲染模板 #
3.1 基本渲染 #
go
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{
"title": "首页",
"message": "Hello, Gin!",
})
})
r.Run()
}
templates/index.html:
html
<!DOCTYPE html>
<html>
<head>
<title>{{ .title }}</title>
</head>
<body>
<h1>{{ .message }}</h1>
</body>
</html>
3.2 传递复杂数据 #
go
type User struct {
ID uint
Name string
Email string
}
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/user", func(c *gin.Context) {
user := User{
ID: 1,
Name: "Alice",
Email: "alice@example.com",
}
c.HTML(200, "user.html", gin.H{
"user": user,
})
})
r.Run()
}
templates/user.html:
html
<!DOCTYPE html>
<html>
<head>
<title>用户信息</title>
</head>
<body>
<h1>用户信息</h1>
<p>ID: {{ .user.ID }}</p>
<p>姓名: {{ .user.Name }}</p>
<p>邮箱: {{ .user.Email }}</p>
</body>
</html>
3.3 传递列表数据 #
go
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/users", func(c *gin.Context) {
users := []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
{ID: 3, Name: "Charlie", Email: "charlie@example.com"},
}
c.HTML(200, "users.html", gin.H{
"users": users,
})
})
r.Run()
}
四、模板语法 #
4.1 变量输出 #
html
<!-- 输出变量 -->
{{ .title }}
<!-- 输出嵌套字段 -->
{{ .user.Name }}
<!-- 定义变量 -->
{{ $name := "Alice" }}
{{ $name }}
4.2 条件判断 #
html
<!-- if判断 -->
{{ if .user }}
<p>用户: {{ .user.Name }}</p>
{{ end }}
<!-- if-else -->
{{ if .isLoggedIn }}
<p>欢迎回来!</p>
{{ else }}
<p>请先登录</p>
{{ end }}
<!-- if-else if-else -->
{{ if eq .status "active" }}
<span class="active">激活</span>
{{ else if eq .status "inactive" }}
<span class="inactive">未激活</span>
{{ else }}
<span class="unknown">未知</span>
{{ end }}
4.3 循环遍历 #
html
<!-- 遍历切片 -->
{{ range .users }}
<div>
<p>ID: {{ .ID }}</p>
<p>姓名: {{ .Name }}</p>
<p>邮箱: {{ .Email }}</p>
</div>
{{ end }}
<!-- 带索引遍历 -->
{{ range $index, $user := .users }}
<div>
<p>序号: {{ $index }}</p>
<p>姓名: {{ $user.Name }}</p>
</div>
{{ end }}
<!-- 遍历Map -->
{{ range $key, $value := .settings }}
<p>{{ $key }}: {{ $value }}</p>
{{ end }}
4.4 管道操作 #
html
<!-- 链式操作 -->
{{ .name | upper }}
<!-- 多个管道 -->
{{ .content | truncate 100 | lower }}
4.5 模板注释 #
html
{{/* 这是注释,不会输出 */}}
{{/*
多行注释
不会被渲染
*/}}
五、模板继承 #
5.1 定义基础模板 #
templates/base.html:
html
<!DOCTYPE html>
<html>
<head>
<title>{{ template "title" . }}</title>
{{ block "head" . }}{{ end }}
</head>
<body>
<header>
{{ block "header" . }}
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
</nav>
{{ end }}
</header>
<main>
{{ block "content" . }}{{ end }}
</main>
<footer>
{{ block "footer" . }}
<p>© 2024 My Website</p>
{{ end }}
</footer>
</body>
</html>
5.2 继承基础模板 #
templates/index.html:
html
{{ define "title" }}首页{{ end }}
{{ define "head" }}
<style>
.hero { color: blue; }
</style>
{{ end }}
{{ define "content" }}
<div class="hero">
<h1>欢迎来到首页</h1>
<p>{{ .message }}</p>
</div>
{{ end }}
templates/about.html:
html
{{ define "title" }}关于我们{{ end }}
{{ define "content" }}
<div class="about">
<h1>关于我们</h1>
<p>这是一个关于页面</p>
</div>
{{ end }}
5.3 渲染继承模板 #
go
func main() {
r := gin.Default()
// 加载所有模板
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(200, "base.html", gin.H{
"message": "Hello, Gin!",
})
})
r.GET("/about", func(c *gin.Context) {
c.HTML(200, "base.html", gin.H{})
})
r.Run()
}
六、模板包含 #
6.1 定义子模板 #
templates/header.html:
html
{{ define "header" }}
<header>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
<a href="/contact">联系</a>
</nav>
</header>
{{ end }}
templates/footer.html:
html
{{ define "footer" }}
<footer>
<p>© 2024 My Website</p>
</footer>
{{ end }}
6.2 包含子模板 #
templates/layout.html:
html
<!DOCTYPE html>
<html>
<head>
<title>{{ .title }}</title>
</head>
<body>
{{ template "header" . }}
<main>
{{ template "content" . }}
</main>
{{ template "footer" . }}
</body>
</html>
6.3 使用template包含 #
html
<!-- 包含其他模板 -->
{{ template "header" . }}
<!-- 包含并传递数据 -->
{{ template "user_card" .user }}
七、模板布局 #
7.1 多布局支持 #
go
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/**/*")
r.GET("/", func(c *gin.Context) {
c.HTML(200, "layouts/main.html", gin.H{
"content": "index.html",
"title": "首页",
})
})
r.GET("/admin", func(c *gin.Context) {
c.HTML(200, "layouts/admin.html", gin.H{
"content": "admin/dashboard.html",
"title": "管理后台",
})
})
r.Run()
}
7.2 动态布局 #
go
func renderWithLayout(c *gin.Context, content string, data gin.H) {
layout := "layouts/main.html"
if isAdmin(c) {
layout = "layouts/admin.html"
}
data["content"] = content
c.HTML(200, layout, data)
}
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/**/*")
r.GET("/dashboard", func(c *gin.Context) {
renderWithLayout(c, "dashboard.html", gin.H{
"title": "仪表盘",
})
})
r.Run()
}
八、错误处理 #
8.1 模板不存在 #
go
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/page", func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.String(500, "模板渲染错误")
}
}()
c.HTML(200, "nonexistent.html", gin.H{})
})
r.Run()
}
8.2 开发模式热重载 #
go
func main() {
r := gin.Default()
// 开发模式下每次请求重新加载模板
if gin.Mode() == gin.DebugMode {
r.Use(func(c *gin.Context) {
r.LoadHTMLGlob("templates/*")
c.Next()
})
} else {
r.LoadHTMLGlob("templates/*")
}
r.Run()
}
九、总结 #
9.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 加载模板 | LoadHTMLGlob、LoadHTMLFiles |
| 渲染模板 | c.HTML() |
| 模板继承 | define、block、template |
| 模板语法 | 变量、条件、循环 |
9.2 最佳实践 #
| 实践 | 说明 |
|---|---|
| 模板继承 | 使用base模板减少重复 |
| 模块化 | 拆分header、footer等组件 |
| 缓存 | 生产环境缓存模板 |
| 安全 | 使用html/template自动转义 |
9.3 下一步 #
现在你已经掌握了模板基础,接下来让我们学习 模板函数,了解自定义模板函数!
最后更新:2026-03-28