Salmon的全栈知识 Salmon的全栈知识
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Gin 介绍
  • Gin 环境搭建
  • golang 程序的热加载
  • Gin 框架中的路由
  • Gin HTML 模板渲染
    • 1、全部模板放在一个目录里面的配置方法
    • 2、模板放在不同目录里面的配置方法
    • 3、gin 模板基本语法
      • 3.1、{ { . } }
      • 3.2、注释
      • 3.3、变量
      • 3.4、移除空格
      • 3.5、比较函数
      • 3.6、条件判断
      • 3.7、range
      • 3.8、With
      • 3.9、预定义函数 (了解)
      • 3.9.1、逻辑运算
      • 3.9.2、数据处理
      • 3.9.3、格式化输出
      • 3.9.4、安全转义
      • 3.9.5、函数调用
      • 3.9.6、总结
      • 3.10、自定义模板函数
      • 3.11、嵌套 template
  • 静态文件服务
  • 路由详解
  • Gin 中自定义控制器
  • Gin 中间件
  • Gin 中自定义 Model
  • Gin 文件上传
  • Gin 中的 Cookie
  • Gin 中的 Session
  • Gin 中使用 GORM 操作 mysql 数据库
  • 原生 SQL 和 SQL 生成器
  • Gin 中使用 GORM 实现表关联查询
  • GORM 中使用事务
  • Gin 中使用 go-ini 加载.ini 配置文件
  • 《Gin》笔记
Salmon
2025-04-03
目录

Gin HTML 模板渲染

# 1、全部模板放在一个目录里面的配置方法

1、我们首先在项目根目录新建 templates 文件夹,然后在文件夹中新建 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<h1>这是一个 html 模板</h1>
<h3>{{.title}}</h3>
</body>
</html>

2、Gin 框架中使用 c.HTML 可以渲染模板,渲染模板前需要使用 LoadHTMLGlob() 或者LoadHTMLFiles() 方法加载模板。

package main

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

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/*")
    //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
    router.GET("/", func(c *gin.Context) {
       c.HTML(http.StatusOK, "index.html", gin.H{"title": "Main website"})
    })

    router.Run(":9090")
}

效果:

image-20250403105318252

# 2、模板放在不同目录里面的配置方法

Gin 框架中如果不同目录下面有同名模板的话我们需要使用下面方法加载模板

注意: 定义模板的时候需要通过 define 定义名称

templates/admin/index.html

相当于给模板定义一个名字 define end 成对出现

{{ define "admin/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<h1>后台模板</h1>
<h3>{{.title}}</h3>
</body>
</html>
{{ end }}

templates/default/index.html

相当于给模板定义一个名字 define end 成对出现

{{ define "default/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<h1>前台模板</h1>
<h3>{{.title}}</h3>
</body>
</html>
{{end}}

业务逻辑

package main

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

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/**/*")
    router.GET("/", func(c *gin.Context) {
       c.HTML(http.StatusOK, "default/index.html", gin.H{"title": "前台首页"})
    })
    router.GET("/admin", func(c *gin.Context) {
       c.HTML(http.StatusOK, "admin/index.html", gin.H{"title": "后台首页"})
    })
    router.Run(":9090")
}

效果:

image-20250403105925210

image-20250403105911324

注意:如果模板在多级目录里面的话需要这样配置 r.LoadHTMLGlob("templates/**/**/*"),其中 /**表示目录

# 3、gin 模板基本语法

# 3.1、{ { . } }

模板语法都包含在{{和}}中间,其中 { { . } } 它们之间的点表示当前对象。

当我们传入一个结构体对象时,我们可以根据.来访问结构体的对应字段。例如:

package main

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

type UserInfo struct {
    Name   string
    Gender string
    Age    int
}

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/**/*")
    user := UserInfo{
       Name: "张三", Gender: "男", Age: 18}
    router.GET("/", func(c *gin.Context) {
       c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{"title": "前台首页", "user": user})
    })
    router.Run(":9090")
}

模板

相当于给模板定义一个名字 define end 成对出现

{{ define "default/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<h1>前台模板</h1>
<h3>{{.title}}</h3>

<h4>{{.user.Name}}</h4>
<h4>{{.user.Age}}</h4>
</body>
</html>
{{end}}

image-20250403110620423

# 3.2、注释

注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。

{{/* a comment */}}

# 3.3、变量

我们还可以在模板中声明变量,用来保存传入模板的数据或其他语句生成的结果。具体语法如下:

<h4>{{$obj := .title}}</h4>

<h4>{{$obj}}</h4>

# 3.4、移除空格

有时候我们在使用模板语法的时候会不可避免的引入一下空格或者换行符,这样模板最终渲染出来的内容可能就和我们想的不一样,这个时候可以使用 { {-语法去除模板内容左侧的所有空白符号, 使用-} } 去除模板内容右侧的所有空白符号。

例如:

{{- .Name -}}

注意:-要紧挨{{和}},同时与模板值之间需要使用空格分隔。

# 3.5、比较函数

布尔函数会将任何类型的零值视为假,其余视为真。

下面是定义为函数的二元比较运算的集合:

  • eq:如果 arg1 == arg2 则返回真
  • ne:如果 arg1 != arg2 则返回真
  • lt:如果 arg1 < arg2 则返回真
  • le:如果 arg1 <= arg2 则返回真
  • gt:如果 arg1 > arg2 则返回真
  • ge:如果 arg1 >= arg2 则返回真

# 3.6、条件判断

Go 模板语法中的条件判断有以下几种:

{{if pipeline}} T1 {{end}}
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
{{if gt .score 60}}
及格
{{else}}
不及格
{{end}}
{{if gt .score 90}}
优秀
{{else if gt .score 60}}
及格
{{else}}
不及格
{{end}}

# 3.7、range

Go 的模板语法中使用 range 关键字进行遍历,有以下两种写法,其中 pipeline 的值必须是数组、切片、字典或者通道。

{{range $key,$value := .obj}}
	{{$value}}
{{end}}

如果 pipeline 的值其长度为 0,不会有任何输出

{{$key,$value := .obj}}
	{{$value}}
{{else}}
	pipeline 的值其长度为 0
{{end}}

如果 pipeline 的值其长度为 0,则会执行 T0。

package main

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

type UserInfo struct {
	Name   string
	Gender string
	Age    int
}

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("templates/**/*")
	user := UserInfo{
		Name: "张三", Gender: "男", Age: 18}
	router.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "default/index.html",
			map[string]interface{}{
				"title": "前台首页",
				"user":  user,
				"hobby": []string{"吃饭", "睡觉", "写代码"},
			})
	})
	router.Run(":9090")
}

// index.html 添加以下内容
{{range $key,$value := .hobby}}
	<p>{{$value}}</p>
{{end}}

image-20250403111855502

# 3.8、With

user := UserInfo{
    Name: "张三", Gender: "男", Age: 18, }
router.GET("/", func(c *gin.Context) {
    c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{ "user": user, })
})

以前要输出数据:

<h4>{{.user.Name}}</h4>
<h4>{{.user.Gender}}</h4>
<h4>{{.user.Age}}</h4>

现在要输出数据:

{{with .user}}
	<h4>姓名:{{.Name}}</h4>
	<h4>性别:{{.user.Gender}}</h4>
	<h4>年龄:{{.Age}}</h4>
{{end}}

简单理解:相当于 var .=.user

# 3.9、预定义函数 (了解)

执行模板时,函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一般不在模板内定义函数,而是使用 Funcs 方法添加函数到模板里。

预定义的全局函数如下:

# 3.9.1、逻辑运算

  • and:返回 第一个 empty 参数 或 最后一个参数。等价于 if x then y else x。

📌 所有参数都会执行。

and x y // 等价于 if x then y else x
  • or:返回 第一个非 empty 参数 或 最后一个参数。等价于 if x then x else y。

📌 所有参数都会执行。

or x y // 等价于 if x then x else y
  • not:返回 参数的布尔值的否定。
not true  // 返回 false
not false // 返回 true

# 3.9.2、数据处理

  • len:返回 参数的长度(整数类型)。
len "hello"     // 返回 5
len [1,2,3,4]   // 返回 4
len {a:1, b:2}  // 返回 2
  • index:取 嵌套索引的值,类似 x[1][2][3]。

📌 要求索引主体是数组、切片或字典。

index x 1 2 3  // 等价于 x[1][2][3]

# 3.9.3、格式化输出

  • print:类似 fmt.Sprint,返回格式化的字符串。
print "Hello" 123 // "Hello123"
  • printf:类似 fmt.Sprintf,支持格式化字符串。
printf "Hello %s" "World"  // "Hello World"
  • println:类似 fmt.Sprintln,返回带换行的格式化字符串。
println "Hello" "World" // "Hello World\n"

# 3.9.4、安全转义

(仅在非 html/template 下可用)

  • html:返回 HTML 转义后的字符串。
html "<b>Bold</b>" // "&lt;b&gt;Bold&lt;/b&gt;"
  • urlquery:返回 URL 查询参数格式化后的值。
urlquery "a=b c" // "a%3Db+c"
  • js:返回 JavaScript 转义后的字符串。
js `"alert('x')"` // "\"alert('x')\""

# 3.9.5、函数调用

  • call:调用函数类型的值,支持 1-2 个返回值(第二个必须是 error 类型)。
    • 如果返回 error 非 nil,模板执行会终止并返回错误。
call .X.Y 1 2  // 等价于 Go 代码中的 dot.X.Y(1, 2)

# 3.9.6、总结

类别 函数 作用
逻辑运算 and 返回第一个 empty 参数或最后一个参数(if x then y else x)
逻辑运算 or 返回第一个非 empty 参数或最后一个参数(if x then x else y)
逻辑运算 not 取布尔值的否定
数据处理 len 计算参数长度
数据处理 index 取嵌套索引的值
格式化输出 print 类似 fmt.Sprint
格式化输出 printf 类似 fmt.Sprintf
格式化输出 println 类似 fmt.Sprintln
安全转义 html HTML 转义(< → <)
安全转义 urlquery URL 查询参数转义
安全转义 js JavaScript 转义
函数调用 call 调用函数,支持 1-2 个返回值

# 3.10、自定义模板函数

router.SetFuncMap(template.FuncMap{
  "formatDate": formatAsDate,
})
package main

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

func formatAsDate(t time.Time) string {
    year, month, day := t.Date()
    return fmt.Sprintf("%d/%02d/%02d", year, month, day)
}
func main() {
    router := gin.Default()
    //注册全局模板函数 注意顺序,注册模板函数需要在加载模板上面
    router.SetFuncMap(template.FuncMap{"formatDate": formatAsDate})
    //加载模板
    router.LoadHTMLGlob("templates/**/*")
    router.GET("/", func(c *gin.Context) {
       c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{"title": "前台首页", "now": time.Now()})
    })
    router.Run(":8080")
}

模板里面的用法

{{.now | formatDate}}
或者
{{formatDate .now }}

效果:

image-20250403141649167

# 3.11、嵌套 template

1、新建 templates/deafult/page_header.html

{{ define "default/page_header.html" }}
	<h1>这是一个头部</h1>
{{end}}

2、外部引入

注意:

1、引入的名字为 page_header.html 中定义的名字

2、引入的时候注意最后的点(.)

{{template "default/page_header.html" .}}

代码:

<!-- 相当于给模板定义一个名字 define end 成对出现-->
{{ define "default/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
{{template "default/page_header.html" .}}
</body>
</html>
{{end}}

效果:

image-20250403142631439

上次更新: 2025/04/03, 16:12:12
Gin 框架中的路由
静态文件服务

← Gin 框架中的路由 静态文件服务→

Theme by Vdoing | Copyright © 2022-2025 Salmon's Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式