当前位置: 首页 > article >正文

Gin渲染

HTML渲染

【示例1】

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

posts/index.tmpl

{{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

{{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模板渲染。

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

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

<!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

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

{{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

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

{{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

body {
    background-color: cadetblue;
}

效果

在这里插入图片描述

使用模板继承

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

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

templates
├── includes
│   ├── home.tmpl
│   └── index.tmpl
├── layouts
│   └── base.tmpl
└── scripts.tmpl

定义一个 loadTemplates 函数

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 函数

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()
}

补充文件路径处理

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

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

JSON渲染

方法1:使用map

main.go1 :map

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

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

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

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渲染

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

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渲染

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

protobuf渲染

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)
})

http://www.kler.cn/news/310749.html

相关文章:

  • 变电站缺陷数据集8307张,带xml标注和txt标注,可以直接用于yolo训练
  • 基于深度学习的零售柜商品识别系统实战思路
  • 阅信云CTO向永清:35岁不应该成为技术职业发展的瓶颈|OceanBase 《DB大咖说》
  • Elasticsearch知识点整理
  • 【计算机毕业设计】医院电子病历
  • 线程池的执行流程
  • Java中的语法糖:让编程更简洁的特性
  • neo4j安装为服务+配置环境变量
  • linux之mysql安装
  • pip清华源地址
  • Vue 自定义指令实战
  • Vue 常见的几种通信方式(总结)
  • ShouldSniffAttr解说
  • Linux: debug:dump_stack 实例
  • 极狐GitLab 重要安全版本:17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10
  • C#使用HttpWebRequest下载文件
  • Java通信协议——UDP通信协议,模拟聊天室(完整详解,附有代码)
  • android含有EditText的键盘弹出后界面的正确处理
  • 人工智能 | 基于ChatGPT开发人工智能服务平台
  • 单片机嵌入式编程中常用技术点
  • Python基础 | 在虚拟环境中安装并在指定文件夹中打开Jupyter notebook
  • Java在零工市场中的应用:构建灵活高效的劳动力平台
  • 【算法】局部敏感哈希(LSH):高效解决相似性搜索问题的利器
  • html页面整合vue2或vue3
  • 选择适合你企业发展的服务器
  • 【Java】网络编程:TCP_IP协议详解(IP协议数据报文及如何解决IPv4不够的状况)
  • C++类和对象(4)
  • Linux平台UOS系统摄像头播放
  • 爬虫--翻页tips
  • .Net Gacutil工具(全局程序集缓存工具)使用教程