参考博客:Gin框架介绍及使用
HTML渲染
我们首先定义一个存放模板文件的templates
文件夹,然后在其内部按照业务分别定义一个posts
文件夹和一个users
文件夹。 posts/index.html
文件的内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{{define "posts/index.html"}}
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta http-equiv = "X-UA-Compatible" content = "ie=edge" >
< title > posts/index</ title >
</ head >
< body >
{{.title}}
</ body >
</ html >
{{end}}
users/index.html
文件的内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{{define "users/index.html"}}
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta http-equiv = "X-UA-Compatible" content = "ie=edge" >
< title > users/index</ title >
</ head >
< body >
{{.title}}
</ body >
</ html >
{{end}}
Gin框架中使用LoadHTMLGlob()
或者LoadHTMLFiles()
方法进行HTML模板渲染。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func main () {
r := gin . Default ()
r . LoadHTMLGlob ( "templates/**/*" )
//r.LoadHTMLFiles("templates/posts/index.html", "templates/users/index.html")
r . GET ( "/posts/index" , func ( c * gin . Context ) {
c . HTML ( http . StatusOK , "posts/index.html" , gin . H {
"title" : "posts/index" ,
})
})
r . GET ( "users/index" , func ( c * gin . Context ) {
c . HTML ( http . StatusOK , "users/index.html" , gin . H {
"title" : "users/index" ,
})
})
r . Run ( ":8080" )
自定义模板函数
定义一个不转义相应内容的safe
模板函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main () {
router := gin . Default ()
router . SetFuncMap ( template . FuncMap {
"safe" : func ( str string ) template . HTML {
return template . HTML ( str )
},
})
router . LoadHTMLFiles ( "./index.tmpl" )
router . GET ( "/index" , func ( c * gin . Context ) {
c . HTML ( http . StatusOK , "index.tmpl" , "<a href='https://liwenzhou.com'>李文周的博客</a>" )
})
router . Run ( ":8080" )
}
在index.tmpl
中使用定义好的safe
模板函数:
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
< html lang = "zh-CN" >
< head >
< title > 修改模板引擎的标识符</ title >
</ head >
< body >
< div > {{ . | safe }}</ div >
</ body >
</ html >
静态文件处理
当我们渲染的HTML文件中引用了静态文件时,我们只需要按照以下方式在渲染页面前调用gin.Static
方法即可。
1
2
3
4
5
6
7
func main () {
r := gin . Default ()
r . Static ( "/static" , "./static" )
r . LoadHTMLGlob ( "templates/**/*" )
// ...
r . Run ( ":8080" )
}
使用模板继承
Gin框架默认都是使用单模板,如果需要使用block template
功能,可以通过"github.com/gin-contrib/multitemplate"
库实现,具体示例如下:
首先,假设我们项目目录下的templates文件夹下有以下模板文件,其中home.tmpl
和index.tmpl
继承了base.tmpl
:
1
2
3
4
5
6
7
templates
├── includes
│ ├── home.tmpl
│ └── index.tmpl
├── layouts
│ └── base.tmpl
└── scripts.tmpl
然后我们定义一个loadTemplates
函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func loadTemplates ( templatesDir string ) multitemplate . Renderer {
r := multitemplate . NewRenderer ()
layouts , err := filepath . Glob ( templatesDir + "/layouts/*.tmpl" )
if err != nil {
panic ( err . Error ())
}
includes , err := filepath . Glob ( templatesDir + "/includes/*.tmpl" )
if err != nil {
panic ( err . Error ())
}
// 为layouts/和includes/目录生成 templates map
for _ , include := range includes {
layoutCopy := make ([] string , len ( layouts ))
copy ( layoutCopy , layouts )
files := append ( layoutCopy , include )
r . AddFromFiles ( filepath . Base ( include ), files ... )
}
return r
}
我们在main
函数中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func indexFunc ( c * gin . Context ){
c . HTML ( http . StatusOK , "index.tmpl" , nil )
}
func homeFunc ( c * gin . Context ){
c . HTML ( http . StatusOK , "home.tmpl" , nil )
}
func main (){
r := gin . Default ()
r . HTMLRender = loadTemplates ( "./templates" )
r . GET ( "/index" , indexFunc )
r . GET ( "/home" , homeFunc )
r . Run ()
}
补充文件路径处理
关于模板文件和静态文件的路径,我们需要根据公司/项目的要求进行设置。可以使用下面的函数获取当前执行程序的路径。
1
2
3
4
5
6
func getCurrentPath () string {
if ex , err := os . Executable (); err == nil {
return filepath . Dir ( ex )
}
return "./"
}
返回Json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func main () {
r := gin . Default ()
// 方法1:使用map
r . GET ( "/json01" , func ( c * gin . Context ) {
data := gin . H { // gin.H is a shortcut for map[string]any
"name" : "tom" ,
"age" : 26 ,
"gender" : "male" ,
}
c . JSON ( http . StatusOK , data )
})
// 方法2:使用struct,使用tag来定制json字段的名称。
r . GET ( "/json02" , func ( c * gin . Context ) {
var person struct {
Name string `json:"name"` // 这里一定要是可导出的,否则json获取不到数据。如果想要指定json字段的名称,可以使用Tag。
Age int `json:"age"`
Gender string `json:"gender"`
}
person . Name = "Jane"
person . Age = 24
person . Gender = "female"
c . JSON ( http . StatusOK , person ) // 传入结构体类型的数据
})
r . Run ( ":9003" )
}