Gin渲染

HTML渲染

【示例1】

首先定义一个存放模板文件的 templates文件夹,然后在其内部按照业务分别定义一个 posts 文件夹和一个 users 文件夹。

posts/index.tmpl

html 复制代码
{{define "posts/index.tmpl"}}
<!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.tmpl

html 复制代码
{{define "users/index.tmpl"}}
<!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}}

main.go

Gin框架中使用 LoadHTMLGlob() 或者 LoadHTMLFiles() 方法进行HTML模板渲染。

go 复制代码
package main

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

func main() {
	r := gin.Default()
	// r.LoadHTMLFiles("templates/index.tmpl", "templates/users/index.tmpl") // 模板解析
	r.LoadHTMLGlob("templates/**/*") // 从templates4目录及其所有子目录中加载所有的文件
	r.GET("/posts/index", func(c *gin.Context) {
		// HTTP请求
		c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ // 模板渲染
			"title": "posts/index.tmpl",
		})
	})

	r.GET("/users/index", func(c *gin.Context) {
		// HTTP请求
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ // 模板渲染
			"title": "users/index.tmpl",
		})
	})
	r.Run(":9090") // 启动server
}

效果

【示例2】

main.go

go 复制代码
package main

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

func main() {
	r := gin.Default()
	r.LoadHTMLFiles("./index.tmpl") // 模板解析
	r.GET("/index", func(c *gin.Context) {
		// HTTP请求
		c.HTML(http.StatusOK, "index.tmpl", gin.H{ // 模板渲染
			"title": "liwenzhou.com",
		})
	})
	r.Run(":9090") // 启动server
}

index.tmpl

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>

效果

自定义模板函数

定义一个不转义相应内容的 safe 模板函数

main.go

go 复制代码
package main

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

func main() {
	r := gin.Default()
	// gin框架中给模板添加自定义函数
	r.SetFuncMap(template.FuncMap{
		"safe": func(str string) template.HTML {
			return template.HTML(str)
		},
	})
	r.LoadHTMLGlob("templates/**/*") // 从templates4目录及其所有子目录中加载所有的文件
	r.GET("/users/index", func(c *gin.Context) {
		// HTTP请求
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ // 模板渲染
			"title": "<a href='https://liwenzhou.com'>李文周的博客</a>",
		})
	})
	r.Run(":9090") // 启动server
}

users/index.tmpl

go 复制代码
{{define "users/index.tmpl"}}
    <!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 | safe}}
    </body>
    </html>
{{end}}

效果

静态文件处理

当渲染的HTML文件中引用了静态文件时,只需要按照以下方式在渲染页面前调用 gin.Static 方法即可。

main.go

go 复制代码
package main

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

// 静态文件: html页面上用到的样式文件 。css js文件 图片
func main() {
	r := gin.Default()
	// 加载静态文件
	r.Static("/xxx", "./statics")
	// gin框架中给模板添加自定义函数
	r.SetFuncMap(template.FuncMap{
		"safe": func(str string) template.HTML {
			return template.HTML(str)
		},
	})
	r.LoadHTMLGlob("templates/**/*") // 从templates4目录及其所有子目录中加载所有的文件
	r.GET("/users/index", func(c *gin.Context) {
		// HTTP请求
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ // 模板渲染
			"title": "<a href='https://liwenzhou.com'>李文周的博客</a>",
		})
	})
	r.Run(":9090") // 启动server
}

users/index.tmpl

html 复制代码
{{define "users/index.tmpl"}}
    <!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">
        <link rel="stylesheet" href="/xxx/index.css">
        <title>users/index</title>
    </head>
    <body>
    {{.title | safe}}
    </body>
    </html>
{{end}}

index.css

css 复制代码
body {
    background-color: cadetblue;
}

效果

使用模板继承

Gin框架默认都是使用单模板,如果需要使用 block template 功能,可以通过 "github.com/gin-contrib/multitemplate" 库实现,具体示例如下:

首先,假设项目目录下的templates文件夹下有以下模板文件,其中 home.tmplindex.tmpl 继承了 base.tmpl

go 复制代码
templates
├── includes
│   ├── home.tmpl
│   └── index.tmpl
├── layouts
│   └── base.tmpl
└── scripts.tmpl

定义一个 loadTemplates 函数

go 复制代码
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 函数

go 复制代码
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()
}

补充文件路径处理

关于模板文件和静态文件的路径,需要根据公司/项目的要求进行设置。可以使用下面的函数获取当前执行程序的路径。

go 复制代码
func getCurrentPath() string {
	if ex, err := os.Executable(); err == nil {
		return filepath.Dir(ex)
	}
	return "./"
}

JSON渲染

方法1:使用map

main.go1 :map

go 复制代码
package main

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

func main() {
	r := gin.Default()
	r.GET("/json", func(c *gin.Context) {
		data := map[string]interface{}{
			"name":    "小王子",
			"message": "hello world!",
			"age":     18,
		}
		c.JSON(http.StatusOK, data)
	})
	r.Run(":9090")
}

main.go2:gin.H

go 复制代码
package main

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

func main() {
	r := gin.Default()
	r.GET("/json", func(c *gin.Context) {
		data := gin.H{"name": "小王子", "message": "hello world!", "age": 18}
		c.JSON(http.StatusOK, data)
	})
	r.Run(":9090")
}

效果

方法2: 结构体

main,go

go 复制代码
package main

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

func main() {
	r := gin.Default()
	type msg struct {
		Name    string
		Message string
		Age     int
	}
	r.GET("/another_json", func(c *gin.Context) {
		data := msg{
			"小王子",
			"Hello golang!",
			18,
		}
		c.JSON(http.StatusOK, data)
	})
	r.Run(":9090")
}

效果

使用tag

go 复制代码
package main

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

func main() {
	r := gin.Default()
	type msg struct {
		// 灵活使用tag来对结构体字段做定制化操作
		Name    string `json:"name"`
		Message string
		Age     int
	}
	r.GET("/another_json", func(c *gin.Context) {
		data := msg{
			"小王子",
			"Hello golang!",
			18,
		}
		c.JSON(http.StatusOK, data)
	})
	r.Run(":9090")
}

XML渲染

注意需要使用具名的结构体类型。

go 复制代码
func main() {
	r := gin.Default()
	// gin.H 是map[string]interface{}的缩写
	r.GET("/someXML", func(c *gin.Context) {
		// 方式一:自己拼接JSON
		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")
}

YMAL渲染

go 复制代码
r.GET("/someYAML", func(c *gin.Context) {
	c.YAML(http.StatusOK, gin.H{"message": "ok", "status": http.StatusOK})
})

protobuf渲染

go 复制代码
r.GET("/someProtoBuf", func(c *gin.Context) {
	reps := []int64{int64(1), int64(2)}
	label := "test"
	// protobuf 的具体定义写在 testdata/protoexample 文件中。
	data := &protoexample.Test{
		Label: &label,
		Reps:  reps,
	}
	// 请注意,数据在响应中变为二进制数据
	// 将输出被 protoexample.Test protobuf 序列化了的数据
	c.ProtoBuf(http.StatusOK, data)
})
相关推荐
桃园码工13 小时前
2-Gin 框架中的路由 --[Gin 框架入门精讲与实战案例]
gin·路由·实战案例
海绵波波10713 小时前
Gin-vue-admin(2):项目初始化
vue.js·golang·gin
海绵波波10713 小时前
Gin-vue-admin(4):项目创建前端一级页面和二级页面
前端·vue.js·gin
程序猿-瑞瑞2 天前
23 go语言(golang) - gin框架安装及使用(四)
开发语言·golang·gin
zyh_0305213 天前
GIN
开发语言·后端·golang·gin
海绵波波1073 天前
Gin-vue-admin(1):环境配置和安装
前端·vue.js·gin
程序猿-瑞瑞4 天前
22 go语言(golang) - gin框架安装及使用(三)
开发语言·golang·gin
Xvens4 天前
Golang Gin Redis+Mysql 同步查询更新删除操作(我的小GO笔记)
redis·golang·gin
ifanatic5 天前
[每周一更]-(第127期):Go新项目-Gin中使用超时中间件实战(11)
中间件·golang·gin
免檒5 天前
基于base64Captcha实现验证码功能
开发语言·后端·中间件·gin