Gin渲染

news2024/11/24 16:27:07

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.coloradmin.cn/o/2142763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络通信基础与实践第二讲】包括互联网概述、互联网发展的三个阶段、互联网的组成、计算机网络的体系结构

一、互联网概述 计算机网络是由若干节点&#xff08;node&#xff09;和连接这些节点的链路&#xff08;link&#xff09;组成。 网络之间还可以通过路由器互联起来&#xff0c;这就构成了一个覆盖范围更大的计算机网络。这样的网络称为互联网。 网络把许多计算机连接在一起…

『功能项目』制作提示主角升级面板【56】

我们打开上一篇55事件中心处理怪物死亡的项目&#xff0c; 本章做的事情是制作提示主角升级的界面&#xff0c;当主角升级时就会被显示出来点击确认即可消失 首先在unity编辑场景制作 在确认按钮对象上添加事件 点击Button将Panel添加至事件框选 在事件函数中选择gameobject.S…

【图像拼接】基于SIFT/SURF特征算法的图像拼接,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于SIFT/SURF特征算法的图像拼接&#xff0c;用matlab实现。 一、案例背景和算法介…

[C#学习笔记]Newtonsoft.Json

视频地址&#xff1a;分享一些Newtonsoft.Json的实用功能与技巧_哔哩哔哩_bilibili 强烈推荐学习C#和WPF的朋友关注此UP&#xff0c;知识点巨多&#xff0c;讲解透彻&#xff01; 一、JsonSerializerSettings 1.1 自动缩进-Formatting 使用Formatting.None进行序列化 var …

流媒体之RTMP协议(其四)

欢迎诸位来阅读在下的博文~ 在这里&#xff0c;在下会不定期发表一些浅薄的知识和经验&#xff0c;望诸位能与在下多多交流&#xff0c;共同努力&#xff01; 江山如画&#xff0c;客心如若&#xff0c;欢迎到访&#xff0c;一展风采 文章目录 前期博客参考书籍一、PTMP简介二…

MyBatis的配置文件详解

01-MyBatis的配置文件详解 创建的接口和xml文件的名字最好写一样的要不然会出问题,然后和接口名相同的xml文件在resources下创建个和接口相同文件夹把xml文件放进去,而且resources下的创建的文件夹需要一级一级的创键,比如:cn创建完,创建tulingxue,然后再创建mapper文件夹才行…

python绘制月亮

import matplotlib import matplotlib.pyplot as plt import moviepy.editor as mpymatplotlib.rcParams[font.family] SimHei# 坐标列表 positions [(0, 0), (1 / 4, 1 / 4), (1 / 3, 1 / 4), (1 / 2, 1 / 4), (2 / 3, 1 / 4),(3 / 4, 1 / 4), (1, 1 / 4), (5 / 4, 1 / 4), …

C++中的容器——vector

1. vector的介绍 vector&#xff1a;vector的底层实际上就是一个数组&#xff08;也称为顺序表&#xff09;&#xff0c;数据是连续存储在数组中的&#xff0c;因此vector是可以使用下标来进行访问的&#xff0c;但是它的大小并不是像数组一样是固定的&#xff0c;而是可以动态…

漳州自闭症寄宿学校,孩子的快乐学习乐园

在温暖而包容的南方都市——广州&#xff0c;藏着一所特别的学校&#xff0c;它以爱为名&#xff0c;为自闭症儿童编织了一个充满希望的未来&#xff0c;这就是星贝育园自闭症儿童寄宿制学校。这里&#xff0c;不仅是知识的殿堂&#xff0c;更是孩子们心灵得以自由飞翔、快乐学…

削峰+限流:秒杀场景下的高并发写请求解决方案

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! 哈喽,大家好!我是小米,一个29岁、活泼积极、热衷分享技术的码农。今天和大家聊一聊应对高并发的写请求这个主题,尤其是在大促、秒杀这种场景下,系统…

【Docker Nexus3】maven 私库

1.部署环境 window 11 x64Docker Desktop 4.34.1 (166053) Docker Engine v27.2.0 1.1.Docker 镜像源 1.1.1.Docker Engine 配置 {"builder": {"features": {"buildkit": true},"gc": {"defaultKeepStorage": "32…

微服务_入门2

文章目录 一、Feign二、Gateway服务网关 一、Feign 来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a; 代码可读性差&#xff0c;编程体验不统一&#xff08;url需要自己在代码中拼写出来&#xff09;参数复杂URL难以维护&#xff0…

Weapons Armor PBR Pack 1 - Fantasy RPG 武器护甲游戏模型

武器和护甲包#1有30个武器和护甲,每个对象都有默认外观,大多数都有网格变形和Substance Painter源文件,用于自定义纹理。 无限PBR&我的哲学 Infinity PBR是十几位艺术家的作品,他们都在做自己最擅长的事情。我想为独立游戏开发者制作最通用、最优质的资产,按照我希望的…

鸿蒙开发之ArkUI 界面篇 四

文字溢出处理、省略号、文字太长的处理用textOverflow&#xff0c;语法格式是&#xff1a; Text.textOverflow({ overflow: TextOverflow; }) 尤其注意&#xff0c;单独的这个设置没有效果&#xff0c;需要和maxLines一起使用才有效果 Text("男频男频男频男频男频男频男…

好代码网同款wordpress主题,完全开源无加密可二开

这个其实就是好代码网站的早期整站打包代码&#xff0c;当时售价198的&#xff0c;现在里面的部分数据已经过期了&#xff0c;只能展示效果&#xff0c;没法下载。所以就只当做主题分享给大家使用。 资源下载类网站目前还是红利期&#xff0c;搞个特价主机和域名&#xff0c;再…

代码随想录Day 46|动态规划完结,leetcode题目:647. 回文子串、516.最长回文子序列

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 题目题目一&#xff1a;647. 回文子串解题思路&#xff1a;暴力解法动态规划 题目二&#xff1a; 516.最长回文子序列解题思路&#xff1a; 动态规划总结动规五部曲基础概念常见问题类型 动态规划…

算法设计与分析(循环赛日程表

目录 循环赛日程表算法介绍代码实现注意事项 小结&#xff1a; 循环赛日程表 在组织和安排体育赛事时&#xff0c;循环赛日程表的编制是一项重要且复杂的任务。循环赛&#xff0c;即每个参赛队伍都要与其他所有队伍进行一场比赛&#xff0c;确保比赛的公平性和所有队伍之间的平…

Linux下的CAN通讯

CAN总线 CAN总线简介 CAN&#xff08;Controller Area Network&#xff09;总线是一种多主从式 <font color red>异步半双工串行 </font> 通信总线&#xff0c;它最早由Bosch公司开发&#xff0c;用于汽车电子系统。CAN总线具有以下特点&#xff1a; 多主从式&a…

JAVA基础面试题总结(十五)——设计模式

面试专题-设计模式 前言 在平时的开发中&#xff0c;涉及到设计模式的有两块内容&#xff0c;第一个是我们平时使用的框架&#xff08;比如spring、mybatis等&#xff09;&#xff0c;第二个是我们自己开发业务使用的设计模式。 面试官一般比较关心的是你在开发过程中&#…

面向对象程序设计(C++)———多态

1.认识多态 多态(polymorphism)的概念&#xff1a;通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)&#xff0c;这⾥我们重点讲运⾏时多态&#xff0c;编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主要就是我们…