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

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 mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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 mapfor _, 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 mainimport ("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 mainimport ("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 mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()type msg struct {Name    stringMessage stringAge     int}r.GET("/another_json", func(c *gin.Context) {data := msg{"小王子","Hello golang!",18,}c.JSON(http.StatusOK, data)})r.Run(":9090")
}

效果

在这里插入图片描述

使用tag

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()type msg struct {// 灵活使用tag来对结构体字段做定制化操作Name    string `json:"name"`Message stringAge     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) {// 方式一:自己拼接JSONc.XML(http.StatusOK, gin.H{"message": "Hello world!"})})r.GET("/moreXML", func(c *gin.Context) {// 方法二:使用结构体type MessageRecord struct {Name    stringMessage stringAge     int}var msg MessageRecordmsg.Name = "小王子"msg.Message = "Hello world!"msg.Age = 18c.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)
})

相关文章:

Gin渲染

HTML渲染 【示例1】 首先定义一个存放模板文件的 templates文件夹&#xff0c;然后在其内部按照业务分别定义一个 posts 文件夹和一个 users 文件夹。 posts/index.tmpl {{define "posts/index.tmpl"}} <!DOCTYPE html> <html lang"en">&…...

前端——JS基础

定义变量&#xff1a;let / var 字符串 字符串拼接&#xff1a; 字符串和数字拼&#xff1a;您.... 25 ; 这个25会转成字符串再拼接 字符串和数组拼&#xff1a;10以内的质数有&#xff1a; [2,3,5,7] > 10以内的质数有&#xff1a;2,3,5,7 字符串长度&#xff1a;leng…...

MATLAB入门教程

MATLAB安装教程可参考链接&#xff1a;matlab怎么安装 matlab安装教程-电脑软件-PHP中文网 1.MATLAB的工作环境 &#xff08;1&#xff09;命令窗(command window) 是对MATLAB进行操作的主要载体。默认情况下&#xff0c;启动MATLAB时就打开命令窗。MATLAB的所有所数…...

muduo - 概要简述

作者&#xff1a;陈硕 编程语言&#xff1a;C 架构模式&#xff1a;Reactor 代码链接&#xff1a;GitHub - chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C11 设计自述&#xff1a;https://www.cnblogs.com/Solstice/archive/2010/08…...

Selenium点击元素的方法

前言 点击方法在web自动化测试中经常用到,下面就来介绍一下selenium常用和不常用的点击方法; 1、常用方法 1.1、使用 click() 方法: 这是最简单和最常用的方法。通过选中要点击的元素,然后使用 click() 方法来触发点击事件。 示例代码: element = self.driver.find_e…...

kali里面搭建docker容器

注意事项&#xff1a;kali版本&#xff0c;镜像源 &#xff08;1&#xff09;权限为管理员&#xff1a; sudo su (2) 更新软件包列表并升级已安装的软件包 apt-get update apt-get upgrade 出错了&#xff0c;应该是更新源出问题了。 &#xff08;3&#xff09;更换镜像源&am…...

WebGL系列教程八(GLSL着色器基础语法)

目录 1 前言2 基本原则3 基本数据类型4 顶点着色器和片元着色器4.1 声明4.2 初始化项目4.3 赋值 5 结构体5.1 声明5.2 赋值 6 函数6.1 基本结构6.2 自定义函数6.3 常用内置函数 7 精度8 其他9 总结 1 前言 通过前七讲&#xff0c;我们已经见过了WebGL中的部分基础语法&#xff…...

go多线程

1、简单使用&#xff08;这个执行完成&#xff0c;如果进程执行比较久&#xff0c;这里不会等待它们结束&#xff09; package mainimport "time"func main() {go func() {println("Hello, World!")}()time.Sleep(1 * time.Second) }2、wg.Add(数量)使用&…...

【话题】如何看待IBM中国研发部裁员?

&#xff08;一&#xff09;背景 在全球化的大趋势下&#xff0c;跨国公司的业务布局一直处于动态调整之中。IBM 作为全球知名的 IT 企业&#xff0c;在中国市场已经运营多年&#xff0c;其在中国的研发中心曾经为公司的全球业务发展做出了重要贡献。近年来&#xff0c;全球经…...

【C/C++】涉及string类的经典OJ编程题

【C/C】涉及string类的经典OJ编程题 一. 把字符串转化成整数&#xff08;atoi&#xff09;解法一&#xff1a;&#xff08;不用long&#xff09;完整代码&#xff1a;解法二&#xff1a;&#xff08;用long&#xff09; 二.字符串相加代码实现&#xff08;含注释&#xff09;&a…...

淘系等电商平台API接口系列:商品详情数据解析,json数据返回参考

——在成长的路上&#xff0c;我们都是同行者。这篇关于商品详情API接口的文章&#xff0c;希望能帮助到您。期待与您继续分享更多API接口的知识&#xff0c;请记得关注Anzexi58哦&#xff01; 在淘系&#xff08;如淘宝、天猫&#xff09;等电商平台中&#xff0c;商品详情数据…...

vue组件之间的数据共享

一、组件之间的关系 1.父子关系 2.兄弟关系 3.后代关系 二、父子组件之间的数据共享 1.父-->子共享数据 父组件通过v-bind属性绑定向子组件共享数据&#xff0c;子组件需要使用props接受数据。 <template><p>父组件</p><Son :msg"msg"…...

LangChain:构建强大的LLM应用的全方位框架

LangChain&#xff1a;构建强大的LLM应用的全方位框架 引言 在人工智能和大语言模型&#xff08;LLMs&#xff09;快速发展的今天&#xff0c;开发者们迫切需要一个强大而灵活的框架来简化LLM应用的开发过程。LangChain应运而生&#xff0c;它不仅提供了丰富的工具和组件&…...

自有平台自有品牌如何利用电商API接口做定价参考(多平台商品详情数据接口)

如今&#xff0c;多数自有商城自有品牌在为产品做定价时都会参考淘宝|天猫|京东等主流电商平台的商品价格以做参考&#xff0c;这一行为的好处主要有以下几点&#xff1a; 通过参考主流平台价格&#xff0c;用户更能了解目标市场中消费者对产品的接受度&#xff0c;从而制定出符…...

三万字长文Java面试题——基础篇(注:该篇博客将会一直维护 最新维护时间:2024年9月18日)

&#x1f9f8;本篇博客重在讲解Java基础的面试题&#xff0c;将会实时更新&#xff0c;欢迎大家添加作者文末联系方式交流 &#x1f4dc;JAVA面试题专栏&#xff1a;JAVA崭新面试题——2024版_dream_ready的博客-CSDN博客 &#x1f4dc;作者首页&#xff1a; dream_ready-CSDN博…...

数学建模——熵权+TOPSIS+肘部法则+系统聚类

文章目录 一、起因二、代码展示 一、起因 我本科的数学建模队长找上我&#xff0c;让我帮她写下matlab代码&#xff0c;当然用的模型还是曾经打比赛的模型&#xff0c;所以虽然代码量多&#xff0c;但是写的很快&#xff0c;也是正逢中秋&#xff0c;有点时间。 当然我也没想到…...

Java | Leetcode Java题解之第403题青蛙过河

题目&#xff1a; 题解&#xff1a; class Solution {public boolean canCross(int[] stones) {int n stones.length;boolean[][] dp new boolean[n][n];dp[0][0] true;for (int i 1; i < n; i) {if (stones[i] - stones[i - 1] > i) {return false;}}for (int i 1…...

828华为云征文|华为Flexus云服务器搭建OnlyOffice私有化在线办公套件

一、引言 在当今数字化办公的时代&#xff0c;在线办公套件的需求日益增长。华为Flexus云服务器凭借其强大的性能和稳定性&#xff0c;为搭建OnlyOffice私有化在线办公套件提供了理想的平台。在2024年9月14日这个充满探索精神的日子里&#xff0c;我们开启利用华为Flexus云服务…...

[Java]maven从入门到进阶

介绍 apache旗下的开源项目,用于管理和构建java项目的工具 官网: Welcome to The Apache Software Foundation! 1.依赖管理 通过简单的配置, 就可以方便的管理项目依赖的资源(jar包), 避免版本冲突问题 优势: 基于项目对象模型(POM),通过一小段描述信息来管理项目的构建 2…...

Leetcode面试经典150题-130.被围绕的区域

给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O 组成&#xff0c;捕获 所有 被围绕的区域&#xff1a; 连接&#xff1a;一个单元格与水平或垂直方向上相邻的单元格连接。区域&#xff1a;连接所有 O 的单元格来形成一个区域。围绕&#xff1a;如果您可以用 X 单…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...