模板渲染 #

一、基本渲染 #

1.1 渲染模板 #

go
app.Get("/", func(c *fiber.Ctx) error {
    return c.Render("index", fiber.Map{
        "Title": "Hello, World!",
    })
})

1.2 模板文件 #

html
<!-- views/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{.Title}}</title>
</head>
<body>
    <h1>{{.Title}}</h1>
</body>
</html>

二、数据传递 #

2.1 传递数据 #

go
app.Get("/user", func(c *fiber.Ctx) error {
    return c.Render("user", fiber.Map{
        "Title": "User Profile",
        "User": fiber.Map{
            "Name":  "John Doe",
            "Email": "john@example.com",
            "Age":   30,
        },
    })
})

2.2 模板中使用 #

html
<h1>{{.User.Name}}</h1>
<p>Email: {{.User.Email}}</p>
<p>Age: {{.User.Age}}</p>

2.3 传递结构体 #

go
type User struct {
    Name  string
    Email string
    Age   int
}

app.Get("/profile", func(c *fiber.Ctx) error {
    user := User{
        Name:  "John Doe",
        Email: "john@example.com",
        Age:   30,
    }
    
    return c.Render("profile", fiber.Map{
        "Title": "Profile",
        "User":  user,
    })
})

三、布局模板 #

3.1 定义布局 #

html
<!-- views/layouts/main.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{{.Title}}</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <header>
        <nav>
            <a href="/">Home</a>
            <a href="/about">About</a>
            <a href="/contact">Contact</a>
        </nav>
    </header>
    
    <main>
        {{template "content" .}}
    </main>
    
    <footer>
        <p>&copy; 2024 My App</p>
    </footer>
    
    <script src="/static/js/app.js"></script>
</body>
</html>

3.2 内容模板 #

html
<!-- views/pages/home.html -->
{{define "content"}}
<h1>Welcome Home</h1>
<p>{{.Message}}</p>
{{end}}

3.3 渲染布局 #

go
app.Get("/", func(c *fiber.Ctx) error {
    return c.Render("pages/home", fiber.Map{
        "Title":   "Home",
        "Message": "Welcome to our website!",
    }, "layouts/main")
})

四、部分模板 #

4.1 定义部分模板 #

html
<!-- views/partials/header.html -->
<header class="header">
    <div class="logo">My App</div>
    <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
    </nav>
</header>

4.2 引用部分模板 #

html
<!-- views/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{.Title}}</title>
</head>
<body>
    {{template "partials/header" .}}
    
    <main>
        <h1>{{.Title}}</h1>
        <p>{{.Content}}</p>
    </main>
</body>
</html>

五、条件渲染 #

5.1 if条件 #

html
{{if .User}}
    <p>Hello, {{.User.Name}}!</p>
{{else}}
    <p>Please <a href="/login">login</a></p>
{{end}}

5.2 多条件 #

html
{{if eq .Status "active"}}
    <span class="badge badge-success">Active</span>
{{else if eq .Status "pending"}}
    <span class="badge badge-warning">Pending</span>
{{else}}
    <span class="badge badge-secondary">Inactive</span>
{{end}}

六、循环渲染 #

6.1 基本循环 #

go
app.Get("/users", func(c *fiber.Ctx) error {
    users := []User{
        {Name: "John", Email: "john@example.com"},
        {Name: "Jane", Email: "jane@example.com"},
        {Name: "Bob", Email: "bob@example.com"},
    }
    
    return c.Render("users", fiber.Map{
        "Title": "Users",
        "Users": users,
    })
})

6.2 模板循环 #

html
<h1>Users</h1>
<ul>
{{range .Users}}
    <li>
        <strong>{{.Name}}</strong>
        <span>{{.Email}}</span>
    </li>
{{end}}
</ul>

6.3 带索引循环 #

html
<table>
    <thead>
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Email</th>
        </tr>
    </thead>
    <tbody>
    {{range $index, $user := .Users}}
        <tr>
            <td>{{add $index 1}}</td>
            <td>{{$user.Name}}</td>
            <td>{{$user.Email}}</td>
        </tr>
    {{end}}
    </tbody>
</table>

七、模板函数 #

7.1 内置函数 #

html
<!-- 字符串转换 -->
<p>{{upper .Name}}</p>
<p>{{lower .Name}}</p>

<!-- 格式化 -->
<p>{{formatDate .Date}}</p>

<!-- 安全HTML -->
{{safe .HTMLContent}}

7.2 自定义函数 #

go
engine := html.New("./views", ".html")

engine.AddFunc("truncate", func(s string, length int) string {
    if len(s) <= length {
        return s
    }
    return s[:length] + "..."
})

engine.AddFunc("currency", func(amount float64) string {
    return fmt.Sprintf("$%.2f", amount)
})

7.3 使用自定义函数 #

html
<p>{{truncate .Description 100}}</p>
<p>Price: {{currency .Price}}</p>

八、错误处理 #

8.1 模板不存在 #

go
app.Use(func(c *fiber.Ctx) error {
    err := c.Next()
    
    if err != nil {
        if strings.Contains(err.Error(), "template") {
            return c.Status(500).SendString("Template error")
        }
    }
    
    return err
})

8.2 错误页面 #

go
app.Use(func(c *fiber.Ctx) error {
    err := c.Next()
    
    if err != nil {
        code := fiber.StatusInternalServerError
        if e, ok := err.(*fiber.Error); ok {
            code = e.Code
        }
        
        return c.Status(code).Render("error", fiber.Map{
            "Code":    code,
            "Message": err.Error(),
        })
    }
    
    return nil
})

九、总结 #

9.1 渲染方法 #

方法 说明
c.Render() 渲染模板
fiber.Map{} 数据传递
布局模板 统一页面结构
部分模板 可复用组件

9.2 下一步 #

现在你已经掌握了模板渲染,接下来让我们学习 静态文件服务,了解如何提供静态资源!

最后更新:2026-03-28