4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]

HTML 模板渲染

下面是使用 Gin 框架在 Go 语言中进行 HTML 模板渲染的四个示例。每个示例都包含了必要的注释来解释代码的作用。

示例1:基本模板渲染

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()

	// 加载HTML模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个简单的路由处理函数,渲染HTML模板
	r.GET("/greet", func(c *gin.Context) {
		// 渲染 "greet.html" 模板,并传递一些数据给模板
		c.HTML(http.StatusOK, "greet.html", gin.H{
			"title":   "Greeting Page",
			"message": "Hello, welcome to the Greeting page!",
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}

templates/greet.html 文件内容如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title>
</head>
<body>
    <h1>{{.message}}</h1>
</body>
</html>

示例2:带有参数的模板渲染

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()

	// 加载HTML模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个带参数的路由处理函数,渲染HTML模板
	r.GET("/user/:name", func(c *gin.Context) {
		// 获取URL路径中的参数
		userName := c.Param("name")

		// 渲染 "profile.html" 模板,并传递用户名称给模板
		c.HTML(http.StatusOK, "profile.html", gin.H{
			"title": "User Profile",
			"name":  userName,
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}

templates/profile.html 文件内容如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title>
</head>
<body>
    <h1>Welcome {{.name}}!</h1>
</body>
</html>

示例3:多模板文件渲染

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()

	// 加载HTML模板文件夹下的所有模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个路由处理函数,渲染多个模板文件
	r.GET("/dashboard", func(c *gin.Context) {
		// 渲染 "header.html" 和 "content.html" 模板文件
		c.HTML(http.StatusOK, "header", gin.H{
			"title": "Dashboard",
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}

templates/dashboard.html 文件内容如下:

html 复制代码
{{define "header"}}
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title>
</head>
<body>
    <header>
        <h1>Header Section</h1>
    </header>
{{end}}

{{define "content"}}
<main>
    <p>This is the content section of the dashboard.</p>
</main>
{{end}}

{{define "footer"}}
<footer>
    <p>Footer Section</p>
</footer>
</body>
</html>
{{end}}

请注意,dashboard.html 中定义了三个模板部分(header, content, footer),它们可以在主模板中被调用。

示例4:模板继承和局部模板

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()

	// 加载HTML模板文件夹下的所有模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个路由处理函数,渲染主模板并包含局部模板
	r.GET("/blog", func(c *gin.Context) {
		// 渲染 "base.html" 主模板,并传递数据给模板
		c.HTML(http.StatusOK, "base.html", gin.H{
			"title": "Blog Page",
			"posts": []string{"Post 1", "Post 2", "Post 3"},
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}

templates/base.html 文件内容如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title>
</head>
<body>
    <header>
        <h1>{{.title}}</h1>
    </header>
    <div id="content">
        {{template "postList" .}}
    </div>
</body>
</html>

templates/postlist.html 文件内容如下:

html 复制代码
{{define "postList"}}
<ul>
    {{range .posts}}
    <li>{{.}}</li>
    {{end}}
</ul>
{{end}}

在这个例子中,base.html 是主模板,而 postlist.html 包含了一个局部模板,它会在主模板中被引用。通过这种方式,可以实现模板的复用和继承,从而简化页面结构和维护工作。

gin 模板基本语法

Gin 框架使用 Go 的标准库 html/template 来处理模板,因此 Gin 模板的基本语法与 Go 的模板语法相同。以下是 Gin 模板的一些基本语法和特性:

变量插值

在模板中插入变量的值,可以使用双大括号 {``{}} 包围变量名。

html 复制代码
<p>Hello, {{.Name}}!</p>
  • . 表示当前上下文的数据结构。
  • 如果传递给模板的是一个 map 或 struct,则可以通过点符号访问其字段或键。

当然,下面是一个使用 Gin 框架和 Go 的 html/template 进行变量插值的简单示例。这个例子展示了如何将数据从 Go 代码传递到 HTML 模板,并在模板中正确显示这些数据。

示例:变量插值
Go 文件(main.go
go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// 定义一个结构体来表示用户信息
type User struct {
	Name    string
	Email   string
	JoinDate time.Time
}

func main() {
	// 创建默认的 Gin 路由器
	r := gin.Default()

	// 加载HTML模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个路由处理函数,渲染HTML模板并传递用户数据
	r.GET("/user", func(c *gin.Context) {
		// 创建一个用户实例
		user := User{
			Name:    "Alice",
			Email:   "alice@example.com",
			JoinDate: time.Now(),
		}

		// 渲染 "user.html" 模板,并传递用户数据给模板
		c.HTML(http.StatusOK, "user.html", gin.H{
			"title": "User Profile",
			"user":  user,
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}
HTML 模板文件(templates/user.html
html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title> <!-- 使用 .title 变量设置页面标题 -->
</head>
<body>
    <h1>User Profile</h1>

    <!-- 使用 .user.Name 和 .user.Email 插入用户名称和电子邮件 -->
    <p>Name: {{.user.Name}}</p>
    <p>Email: {{.user.Email}}</p>
    
    <!-- 格式化并插入用户的加入日期 -->
    <p>Joined on: {{.user.JoinDate.Format "2006-01-02"}}</p>

    <!-- 如果你想确保输出是安全的HTML(例如包含标签),可以使用 template.HTML 类型 -->

</body>
</html>
代码注释解释
  1. Go 文件 (main.go)

    • User 结构体定义了用户信息的字段。
    • r.LoadHTMLGlob("templates/*") 用于加载所有位于 templates/ 目录下的HTML模板文件。
    • /user 路由处理函数中,创建了一个 User 实例,并通过 c.HTML() 方法将此实例以及页面标题一起传递给模板。
    • gin.H{} 是一个快捷方式来创建一个 map,用于存储传递给模板的数据。
  2. HTML 模板文件 (templates/user.html)

    • 使用 {``{.title}} 来插入来自 Go 代码中的页面标题。
    • 使用 {``{.user.Name}}{``{.user.Email}} 来插入用户的名字和邮箱地址。
    • 使用 .user.JoinDate.Format "2006-01-02" 来格式化时间戳为可读的日期格式。
    • 注释部分展示了如何使用 template.HTML 来输出原始HTML内容,但需要注意这可能带来安全风险,因此只有在确定内容是安全的情况下才应使用。

通过这种方式,你可以在 Go 代码和 HTML 模板之间传递数据,并且利用 Go 的模板引擎来进行动态内容生成。

函数调用

可以在模板中调用函数,并且可以将结果直接插入到 HTML 中。

html 复制代码
<p>The result is: {{add 1 2}}</p>
  • 在上面的例子中,add 是一个自定义函数,它接收两个参数并返回它们的和。

条件语句

可以使用 ifelse 进行条件判断。

html 复制代码
{{if .IsAdmin}}
    <p>Welcome Admin!</p>
{{else}}
    <p>Welcome User!</p>
{{end}}
  • 支持 ifelse ifelse 结构。

下面是一个使用 Gin 框架和 Go 的 html/template 进行条件语句处理的简单示例。这个例子展示了如何在模板中根据传递的数据执行不同的逻辑分支。

示例:条件语句
Go 文件(main.go
go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// 定义一个结构体来表示用户信息
type User struct {
	Name    string
	IsAdmin bool
}

func main() {
	// 创建默认的 Gin 路由器
	r := gin.Default()

	// 加载HTML模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个路由处理函数,渲染HTML模板并传递用户数据
	r.GET("/user", func(c *gin.Context) {
		// 创建两个不同权限级别的用户实例
		user1 := User{
			Name:    "Alice",
			IsAdmin: true,
		}
		user2 := User{
			Name:    "Bob",
			IsAdmin: false,
		}

		// 根据查询参数 'name' 来决定传递哪个用户实例给模板
		name := c.Query("name")
		var user User
		if name == "Alice" {
			user = user1
		} else {
			user = user2
		}

		// 渲染 "profile.html" 模板,并传递用户数据给模板
		c.HTML(http.StatusOK, "profile.html", gin.H{
			"title": "User Profile",
			"user":  user,
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}
HTML 模板文件(templates/profile.html
html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title> <!-- 使用 .title 变量设置页面标题 -->
</head>
<body>
    <h1>User Profile</h1>

    <!-- 插入用户名 -->
    <p>Name: {{.user.Name}}</p>

    <!-- 使用 if-else 语句来判断用户是否为管理员 -->
    {{if .user.IsAdmin}}
        <p>Welcome Admin!</p>
        <p>You have administrative privileges.</p>
    {{else}}
        <p>Welcome User!</p>
        <p>You do not have administrative privileges.</p>
    {{end}}

    <!-- 你还可以添加更多的逻辑分支,例如 elseif -->
    <!-- 
    {{if .user.IsAdmin}}
        <p>Welcome Admin!</p>
    {{else if .user.IsModerator}}
        <p>Welcome Moderator!</p>
    {{else}}
        <p>Welcome User!</p>
    {{end}}
    -->
</body>
</html>
代码注释解释
  1. Go 文件 (main.go)

    • User 结构体定义了用户信息的字段,包括名字和是否是管理员。
    • /user 路由处理函数中,创建了两个不同权限级别的 User 实例 (user1user2)。
    • 根据 URL 查询参数 name 的值选择要传递给模板的用户实例。
    • 使用 c.HTML() 方法将选定的用户实例以及页面标题一起传递给模板。
  2. HTML 模板文件 (templates/profile.html)

    • 使用 {``{.title}} 来插入来自 Go 代码中的页面标题。
    • 使用 {``{.user.Name}} 来插入用户的名称。
    • 使用 {``{if .user.IsAdmin}} ... {``{else}} ... {``{end}} 来进行条件判断:
      • 如果用户是管理员,则显示欢迎管理员的消息;
      • 否则,显示普通用户的欢迎消息。
    • 注释部分展示了如何使用 if-else if-else 语句来进行多分支逻辑判断,虽然在这个例子中没有用到 IsModerator 字段,但这是为了展示更复杂的条件逻辑。

通过这种方式,你可以在 Go 代码和 HTML 模板之间传递数据,并且利用 Go 的模板引擎来进行动态内容生成,同时可以根据条件改变页面内容。

循环

可以使用 range 对数组、切片、map 等进行迭代。

html 复制代码
<ul>
    {{range .Items}}
        <li>{{.}}</li>
    {{end}}
</ul>
  • .range 内部表示当前迭代项。

下面是一个使用 Gin 框架和 Go 的 html/template 进行循环语句处理的简单示例。这个例子展示了如何在模板中遍历一个列表,并根据列表中的数据动态生成 HTML 内容。

示例:循环语句
Go 文件(main.go
go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// 定义一个结构体来表示项目信息
type Project struct {
	Name     string
	Status   string
}

func main() {
	// 创建默认的 Gin 路由器
	r := gin.Default()

	// 加载HTML模板文件
	r.LoadHTMLGlob("templates/*")

	// 定义一个路由处理函数,渲染HTML模板并传递项目列表数据
	r.GET("/projects", func(c *gin.Context) {
		// 创建一些项目实例
		projects := []Project{
			{Name: "Project Alpha", Status: "Active"},
			{Name: "Project Beta", Status: "Completed"},
			{Name: "Project Gamma", Status: "Pending"},
		}

		// 渲染 "projects.html" 模板,并传递项目列表给模板
		c.HTML(http.StatusOK, "projects.html", gin.H{
			"title":    "Project List",
			"projects": projects,
		})
	})

	// 启动HTTP服务,默认监听0.0.0.0:8080
	r.Run()
}

HTML 模板文件(templates/projects.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>{{.title}}</title> <!-- 使用 .title 变量设置页面标题 -->
</head>
<body>
    <h1>Project List</h1>

    <!-- 使用 range 语句遍历项目列表 -->
    <ul>
        {{range .projects}}
            <li>
                <strong>{{.Name}}</strong> - Status: {{.Status}}
                <!-- 根据项目状态添加不同类名或显示不同图标 -->
                {{if eq .Status "Active"}}
                    <span class="badge badge-success">Active</span>
                {{else if eq .Status "Completed"}}
                    <span class="badge badge-primary">Completed</span>
                {{else}}
                    <span class="badge badge-warning">Pending</span>
                {{end}}
            </li>
        {{end}}
    </ul>
</body>
</html>
代码注释解释
  1. Go 文件 (main.go)

    • Project 结构体定义了项目信息的字段,包括名称和状态。
    • /projects 路由处理函数中,创建了一个包含多个项目的切片 projects
    • 使用 c.HTML() 方法将项目列表以及页面标题一起传递给模板。
  2. HTML 模板文件 (templates/projects.html)

    • 使用 {``{.title}} 来插入来自 Go 代码中的页面标题。
    • 使用 {``{range .projects}} ... {``{end}} 来遍历从 Go 代码传递过来的 projects 切片。
      • 对于每个项目,使用 {``{.Name}}{``{.Status}} 插入项目名称和状态。
      • 使用嵌套的条件语句 {``{if eq .Status "Active"}} ... {``{else if eq .Status "Completed"}} ... {``{else}} ... {``{end}} 根据项目的状态来决定显示的内容或样式。
    • {``{range}} 循环会为每个项目生成一个 <li> 元素,从而动态地构建一个无序列表。

通过这种方式,你可以在 Go 代码和 HTML 模板之间传递数据,并且利用 Go 的模板引擎来进行动态内容生成,同时可以根据循环中的数据动态改变页面内容。这种方法非常适合用于展示列表、表格或其他需要重复元素的界面。

模板继承与包含

定义模板块

可以定义多个模板块,然后在主模板中引用它们。

html 复制代码
{{define "header"}}
<header>
    <h1>Site Header</h1>
</header>
{{end}}

{{define "content"}}
<main>
    <p>Main content goes here.</p>
</main>
{{end}}

{{define "footer"}}
<footer>
    <p>Site Footer</p>
</footer>
{{end}}
引用模板块

在主模板中引用之前定义的模板块。

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>
    {{template "header" .}}
    {{template "content" .}}
    {{template "footer" .}}
</body>
</html>

转义输出

Go 的 html/template 会自动转义输出以防止 XSS(跨站脚本攻击)。

html 复制代码
<p>User input: {{.UserInput}}</p>
  • 如果 .UserInput 包含 HTML 标签或特殊字符,这些内容会被转义,从而安全地显示为纯文本。

原始HTML输出

如果确实需要输出原始 HTML,可以使用 template.HTML 类型。

go 复制代码
data := gin.H{
    "RawHTML": template.HTML("<strong>Bold Text</strong>"),
}
html 复制代码
<div>{{.RawHTML}}</div>
  • 注意,只有当你确定内容是安全的时候才应该这样做,因为这可能会带来安全风险。

注释

模板中也可以包含注释,这些注释不会出现在最终的 HTML 输出中。

html 复制代码
{{/* This is a comment and will not be rendered */}}

自定义函数

你还可以注册自定义函数,以便在模板中使用。

go 复制代码
func init() {
    gin.Template.FuncMap = template.FuncMap{
        "formatAsDate": formatAsDate,
    }
}

func formatAsDate(t time.Time) string {
    return t.Format("2006-01-02")
}
html 复制代码
<p>Date: {{formatAsDate .CreatedAt}}</p>

以上就是 Gin 模板的基本语法和一些常用的功能。通过这些功能,你可以创建动态且安全的 HTML 页面。

gin 模板基本语法 循环语句 1个示例 代码需要注释

相关推荐
黑客老陈9 分钟前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
运维·服务器·前端·网络·安全·web3·xss
正小安14 分钟前
Vite系列课程 | 11. Vite 配置文件中 CSS 配置(Modules 模块化篇)
前端·vite
暴富的Tdy42 分钟前
【CryptoJS库AES加密】
前端·javascript·vue.js
neeef_se42 分钟前
Vue中使用a标签下载静态资源文件(比如excel、pdf等),纯前端操作
前端·vue.js·excel
m0_748235611 小时前
web 渗透学习指南——初学者防入狱篇
前端
℘团子এ1 小时前
js和html中,将Excel文件渲染在页面上
javascript·html·excel
z千鑫1 小时前
【前端】入门指南:Vue中使用Node.js进行数据库CRUD操作的详细步骤
前端·vue.js·node.js
m0_748250742 小时前
Web入门常用标签、属性、属性值
前端
m0_748230442 小时前
SSE(Server-Sent Events)返回n ,前端接收数据时被错误的截断【如何避免SSE消息中的换行符或回车符被解释为事件消息的结束】
前端