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 18
| func main() { r := gin.Default() r.LoadHTMLGlob("templates/**/*") 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()) } 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
| func main() { r := gin.Default()
r.GET("/someJSON", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "Hello world!"}) }) r.GET("/moreJSON", func(c *gin.Context) { var msg struct { Name string `json:"user"` Message string Age int } msg.Name = "小王子" msg.Message = "Hello world!" msg.Age = 18 c.JSON(http.StatusOK, msg) }) r.Run(":8080") }
|
XML渲染
注意需要使用具名的结构体类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| func main() { r := gin.Default() r.GET("/someXML", func(c *gin.Context) { c.XML(http.StatusOK, gin.H{"message": "Hello world!"}) }) r.GET("/moreXML", func(c *gin.Context) { type MessageRecord struct { Name string Message string Age int } var msg MessageRecord msg.Name = "小王子" msg.Message = "Hello world!" msg.Age = 18 c.XML(http.StatusOK, msg) }) r.Run(":8080") }
|