Go Web下gin框架的模板渲染

〇、前言

Gin框架是一个用于构建Web应用程序的轻量级Web框架,使用Go语言开发。它具有高性能、低内存占用和快速路由匹配的特点,旨在提供简单、快速的方式来开发可扩展的Web应用程序。
Gin框架的设计目标是保持简单和易于使用,同时提供足够的灵活性和扩展性,使开发人员能够根据项目的需求进行定制。它提供了许多有用的功能,如中间件支持、路由组、请求参数解析、模板渲染等,使开发人员能够快速构建高效的Web应用程序。
以下是Gin框架的一些主要特性:

  • 快速的性能:Gin框架采用了高性能的路由引擎,使请求路由匹配变得非常快速。

  • 中间件支持:Gin框架支持中间件机制,允许你在请求处理过程中添加自定义的中间件,用于处理认证、日志记录、错误处理等功能。

  • 路由组:Gin框架允许将路由按照逻辑组织成路由组,使代码结构更清晰,并且可以为不同的路由组添加不同的中间件。

  • 请求参数解析:Gin框架提供了方便的方法来解析请求中的参数,包括查询字符串参数、表单参数、JSON参数等。

  • 模板渲染:虽然Gin框架本身不提供模板引擎,但它与多种模板引擎库(如html/template、pongo2等)集成,使你能够方便地进行模板渲染。

  • 错误处理:Gin框架提供了内置的错误处理机制,可以捕获和处理应用程序中的错误,并返回适当的错误响应。

总体而言,Gin框架是一个简单、轻量级但功能强大的Web框架,非常适合构建高性能、可扩展的Web应用程序。它在Go语言社区中得到广泛的认可,并被许多开发人员用于构建各种类型的Web应用程序。

一、html/template

html/template是Go语言标准库中的一个包,用于生成和渲染HTML模板。它提供了一种安全且灵活的方式来生成HTML输出,支持模板继承、变量替换、条件语句、循环结构等功能。

html/template包的主要目标是防止常见的Web安全漏洞,如跨站脚本攻击(XSS)。它通过自动进行HTML转义和编码来确保生成的HTML是安全的,并防止恶意用户注入恶意代码。

使用html/template包可以将动态数据与静态HTML模板分离,使代码更易于维护和重用。你可以定义模板文件,然后将数据传递给模板进行渲染,最后生成最终的HTML输出。

(一)初次渲染

先创建一个名为 hello.tmpl的文件:

<!DOCTYPE html>
<html lang="zh-CN">
<head><title>Hello</title>
</head>
<body>
<p>hello, {{.}}</p>
</body>
</html>

这里的{{.}}中的.就代表了我们要填充的东东,接着创建我们的main.go函数:

package mainimport ("fmt""html/template""net/http"
)func sayHello(w http.ResponseWriter, r *http.Request) {// 请勿刻舟求剑,用绝对地址t, err := template.ParseFiles("/Users/luliang/GoLand/gin_practice/chap1/hello.tmpl")if err != nil {fmt.Println("http server failed:%V", err)return}// 渲染模板err = t.Execute(w, "小王子!")if err != nil {fmt.Println("http server failed:%V", err)return}
}
func main() {http.HandleFunc("/hello", sayHello)err := http.ListenAndServe(":9000", nil)if err != nil {fmt.Println("http server failed:%V", err)return}
}

使用html/template进行HTML模板渲染的一般步骤如下:

  • 定义模板:
    首先,你需要定义HTML模板。可以在代码中直接定义模板字符串,也可以将模板保存在独立的文件中。比如我们创建了模板:hello.tmpl

  • 创建模板对象:
    使用template.New()函数创建一个模板对象。你可以选择为模板对象指定一个名称,以便在渲染过程中引用它。

  • 解析模板:
    使用模板对象的Parse()或ParseFiles()方法解析模板内容。如果模板内容保存在单独的文件中,可以使用ParseFiles()方法解析文件内容并关联到模板对象。

  • 渲染模板:
    创建一个用于存储模板数据的数据结构,并将数据传递给模板对象的Execute()方法。该方法将渲染模板并将结果写入指定的输出位置(如os.Stdout或http.ResponseWriter)。

在浏览器中输入:127.0.0.0:9000/hello就可以看到结果:hello, 小王子!

(二)传入其它数据进行渲染

上次渲染,我们用的是这一句:err = t.Execute(w, "小王子!"),可以看到我们传入了一个字符串而已。这次我们打算传点稍微不同的其它数据。继续编写模板test.tmpl:

<!DOCTYPE html>
<html lang="zh-CN">
<head><title>Hello</title>
</head>
<body>
<p>姓名: {{.Name}}</p>
<p>年龄: {{.Age}}</p>
<p>性别: {{.Gander}}</p>
</body>
</html>

可以看到,我们的模板稍微复杂起来了!继续编写 main.go

package mainimport ("fmt""html/template""net/http"
)type User struct {Name   stringGander string // 首字母是否大小写,作为是否对外暴露的标识Age    int
}func sayHello(w http.ResponseWriter, r *http.Request) {// 定义模板u1 := User{Name:   "小王子",Gander: "男",Age:    19,}// 解析模板t, err := template.ParseFiles("/Users/luliang/GoLand/gin_practice/chap2/test.tmpl")if err != nil {fmt.Println("ParseFiles failed:%V", err)return}err = t.Execute(w, u1)if err != nil {return}}
func main() {http.HandleFunc("/hello", sayHello)err := http.ListenAndServe(":9000", nil)if err != nil {fmt.Println("http server failed:%V", err)return}}

可以看到我们在里面定义了一个结构类型 User,传入了一个 User 对象 u1:err = t.Execute(w, u1)

type User struct {Name   stringGander string // 首字母是否大小写,作为是否对外暴露的标识Age    int
}

赶紧看看运行结果,可以看到结果符合预期:

姓名: 小王子
年龄: 19
性别: 男

(三)定义函数参与渲染

定义我们的模板:f.tmpl:

<!DOCTYPE html>
<html lang="zh-CN">
<head><title>hello</title>
</head>
<body>
{{ kua . }}
</body>
</html>

可以看到,我们的模板里面有一个函数名字叫做 kua,没错,这就是我们要的函数。

编写main.go:

package main
import ("fmt""html/template""net/http"
)
func f(w http.ResponseWriter, r *http.Request) {// 定义模板k := func(name string) (string, error) {return name + "太棒了!", nil}t := template.New("f.tmpl")t.Funcs(template.FuncMap{"kua": k,})// 解析模板_, err := t.ParseFiles("/Users/luliang/GoLand/gin_practice/chap3/f.tmpl")if err != nil {return}// 渲染模板err = t.Execute(w, "小王子")if err != nil {return}
}
func main() {http.HandleFunc("/hello", f)err := http.ListenAndServe(":9002", nil)if err != nil {fmt.Println("http server failed:%V", err)return}}

可以看到,我用了一个关键语句将函数kua 关联到了模板:

	t.Funcs(template.FuncMap{"kua": k,})

点击运行,可以看到结果:小王子太棒了!

(四)c.HTML() 渲染

在Gin框架中,可以使用c.HTML()方法来进行HTML模板渲染。该方法接收HTTP状态码、模板名称和渲染所需的数据作为参数。

编写模板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>

可以看到我们只需渲染传入对象的 title 值,编写 main.go:

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.LoadHTMLFiles("/Users/luliang/GoLand/gin_practice/chap4/index.tmpl")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "你好,前端真是太有意思了!",})})r.Run(":9091")
}

首先,创建一个 gin.default()路由对象,然后给该对象载入已经写好的模板文件,之后就可以用 GET 函数进行请求了。
先看看 GET 是什么东西:

// GET is a shortcut for router.Handle("GET", path, handlers).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {return group.handle(http.MethodGet, relativePath, handlers)
}

它说,GET 是router.Handle("GET", path, handlers)的一个捷径。再看看router.Handle("GET", path, handlers)是什么东西:

func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {absolutePath := group.calculateAbsolutePath(relativePath)handlers = group.combineHandlers(handlers)group.engine.addRoute(httpMethod, absolutePath, handlers)return group.returnObj()
}// Handle registers a new request handle and middleware with the given path and method.
// The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes.
// See the example code in GitHub.
//
// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut
// functions can be used.
//
// This function is intended for bulk loading and to allow the usage of less
// frequently used, non-standardized or custom methods (e.g. for internal
// communication with a proxy).

原来就是做了一下中间处理,注册了一个新的请求句柄。它还说GET, POST, PUT, PATCH、DELETE 都有类似的捷径。之后在 handlers中放一个匿名函数:

func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "你好,前端真是太有意思了!",})}

这个函数就是用于渲染的函数。猜测c.HTML()依然是一个 shortcut:

// HTML renders the HTTP template specified by its file name.
// It also updates the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (c *Context) HTML(code int, name string, obj any) {instance := c.engine.HTMLRender.Instance(name, obj)c.Render(code, instance)
}

可以看到真正干活的还是 Render()

点击运行,结果为:你好,前端真是太有意思了!

(五)从多个模板中选择一个进行渲染

如果要渲染多个文件,该如何操作?比如我们通过输入不同的网站,服务器这时只需要选择不同的模板进行渲染就好。在这里创建了两个模板文件,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}}

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

这里使用了{{define "posts/index.tmpl"}}...{{end}}结构,对模板文件进行了命名。
编写main.go:

package mainimport ("github.com/gin-gonic/gin""html/template""net/http"
)func main() {r := gin.Default()r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")r.GET("/posts/index", func(c *gin.Context) {c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{"title": "posts/index.tmpl",})})r.GET("/users/index", func(c *gin.Context) {c.HTML(http.StatusOK, "users/index.tmpl", gin.H{"title": "送你到百度!",})})r.Run(":9091")
}

我们在在浏览器地址栏输入http://127.0.0.1:9091/users/index可以得到:送你到百度!;而输入http://127.0.0.1:9091/posts/index可以得到:posts/index.tmpl

(六)加点东西,使得事情朝着有意思的方向进行!

我们为了使得网页画面更有趣,这里使用了多个文件,分别是index.css、index.js。编写:index.css:

body {background-color: #00a7d0;
}

没错只有一句话。接下来编写 index.js:

alert("Hello, Web!")

没错,也只有一句话。然后,我们把 css、js 文件引入到 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}}<script src="/xxx/index.js"></script></body></html>
{{end}}

接下来写main.go:

package mainimport ("github.com/gin-gonic/gin""html/template""net/http"
)func main() {r := gin.Default()// 加载静态文件r.Static("/xxx", "/Users/luliang/GoLand/gin_practice/chap5/statics")r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")r.GET("/posts/index", func(c *gin.Context) {c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{"title": "posts/index.tmpl",})})r.GET("/users/index", func(c *gin.Context) {c.HTML(http.StatusOK, "users/index.tmpl", gin.H{"title": "送你到百度!",})})r.Run(":9091")
}

因为我们要把 css、js 文件加载进去,因此要用 r.Static()函数把放置静态文件的目录加入进去。为了复用,第一个参数“/xxx”的意思是,只要index.tmpl文件中存在“/xxx”字段就直接指到我们设置的目录。
运行结果:首先 js 文件会首先渲染:
在这里插入图片描述
之后,css 文件会渲染:在这里插入图片描述

可以看到这里出现了一个超链接,那是因为我们在这个字符后面插入了一个函数:

// 添加自定义函数r.SetFuncMap(template.FuncMap{"safe": func(str string) template.HTML {return template.HTML(str)},})

配合 index.tmpl,就可以了。
在这里插入图片描述

三、利用已有模板进行部署

通过以上的例子,终于学会了在模板中插入大量的css、js 进行渲染了!
首先找到某个网站,比如站长之家,下载一个模板:在这里插入图片描述
选择第一个,下载之后解压:在这里插入图片描述

static 外面的 index.html有用,其它都可以忽略。把 static 里面的文件夹复制到我们的工作目录:在这里插入图片描述
同时,把 index.html文件复制到 posts(无所谓,强迫症而已),就可以使用了。

	r.GET("/home", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})

这样,在地址栏输入:http://127.0.0.1:9091/home,就可以看到效果了:
在这里插入图片描述
渲染的相当完美!这里会存在一些小细节,比如在 index.html文件中需要把 css
、js文件的地址进行变更,变更到你放置这些文件的地址:
在这里插入图片描述
代码附上main.go

package mainimport ("github.com/gin-gonic/gin""html/template""net/http"
)func main() {r := gin.Default()// 加载静态文件r.Static("/xxx", "/Users/luliang/GoLand/gin_practice/chap5/statics")// 添加自定义函数r.SetFuncMap(template.FuncMap{"safe": func(str string) template.HTML {return template.HTML(str)},})r.LoadHTMLGlob("/Users/luliang/GoLand/gin_practice/chap5/templates/**/*")r.GET("/posts/index", func(c *gin.Context) {c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{"title": "posts/index.tmpl",})})r.GET("/users/index", func(c *gin.Context) {c.HTML(http.StatusOK, "users/index.tmpl", gin.H{"title": "<a href='https://www.baidu.com'>送你到百度!</a>",})})r.GET("/home", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})r.Run(":9091")
}

这意味着,我们以后要想写网页,根本不需要进行大量的无意义的编程,利用 ChatGPT,我们可以写出大量的优秀的css、js 网页,我们要做的只是进行适量的改动,这将极大地丰富我们的创造力!

四、总结

本文从简单到难,对Go Web中 gin 框架下的模板渲染进行了简单的阐述。

全文完,感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28990.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【VINS-Fusion】学习笔记

配置文件-config\euroc\euroc_stereo_imu_config.yaml %YAML:1.0#common parameters #support: 1 imu 1 cam; 1 imu 2 cam: 2 cam; #1个mui&#xff0c;双目相机 imu: 1 num_of_cam: 2 imu_topic: "/imu0" image0_topic: "/cam0/image_raw" im…

Qt6教程之三(3) QtWedget自定义控件

在之前的博客中&#xff0c;我们使用的控件都是Qt官方提供的&#xff0c;对于控件的特性也只能被动地接受&#xff0c;为了打破这种束缚&#xff0c;可以按照自己的想法来定义控件。 不过自定义控件必须遵守Qt官方的一套自定义控件规则&#xff0c;在规则之下我们就可以定义属…

基于TextRank+Seq2Seq+Pyqt5文章摘要标题关键词辅助生成系统(含全部python工程源码)+训练数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境TextRank环境TensorFlow环境PyQt5及Qt Designer运行环境 模块实现1. 数据预处理2. 抽取摘要3. 模型搭建与编译4. 模型训练与保存5. 图形化界面的开发6. 应用封装 系统测试1. 训练困惑度2. 测试效果3. 模型应用 工…

基于langchain-chatglm本地知识库得部署

项目的技术组成 LLM模型 大型语言模型&#xff08;LLM&#xff0c;是large language model&#xff09;是一种人工智能模型&#xff0c;旨在理解和生成人类语言。它们通过在大量文本数据上进行训练&#xff0c;能够执行多种任务&#xff0c;包括文本总结、翻译、情感分析等。L…

电信卡流量套餐超40G后,该如何解除网速限制?

在和朋友开视频的时候&#xff0c;朋友那边忽然网络中断了&#xff0c;过了会他给我发了一张图片过来&#xff0c;图片如下&#xff1a; 朋友的手机是电信的&#xff0c; 然后我们就在网上查各种解除限制的信息&#xff0c;首先我们按照短信上的提示发送SWFJ到10001&#xff0c…

流量控制与RateLimiter

一背景 如何提高系统的稳定性&#xff0c;简单来说除了加机器外就是服务降级、限流。加机器就是常说的分布式&#xff0c;从整个架构的稳定性角度看&#xff0c;一般SOA每个接口的所能提供的单位时间服务能力是有上限。假如超过服务能力&#xff0c;一般会造成整个接口服务停顿…

异常流量检测

项目目标是为了检测网络异常流量&#xff0c;防止网络攻击行为&#xff0c;本人参与了初期的工作&#xff0c;进行了文献阅读-数据处理-模型构建-参数优化工作。 网络攻击行为主要分为Dos、U2R、Probe等&#xff0c;其对应的流量异常特征为集合异常、点异常、上下文异常。 点异…

网络流量监控分析工具ntopng的安装与使用

我写这篇文章的起因&#xff1a;网上介绍ntopng这款工具的博客不算很多&#xff0c;而且安装方法基本没一个行得通&#xff08;可能是版本更新太快了&#xff09;&#xff0c;我在安装过程中遇到了一些问题&#xff0c;想跟大家分享下&#xff1b;其次&#xff0c;在讲使用方法…

流量异常检测

https://mp.weixin.qq.com/s/9h-hOt630W6k077Rupc9CA 流量异常检测主要有以下三个难点&#xff1a; 流量的大小会随着用户行为发生变化。对于大部分百度云上的业务&#xff0c;白天的访问流量较高&#xff0c;深夜的访问流量较低。这使得流量水位值存在上下文相关性&#xff0…

Android应用流量统计——NetworkStatsManager使用

在没有Root的情况下&#xff0c;Android应用流量统计在6.0之前一直没有太好的办法&#xff0c;官方虽然提供了TrafficStats&#xff0c;但其主要功能是设备启动以来流量的统计信息&#xff0c;和时间信息无法很好的配合。最近再看TrafficStats类时&#xff0c;发现说明中提到&a…

仿设置流量使用——细讲android获取流量使用情况,以及解决调用流量接口不准问题(非TrafficStats,而是NetworkStatsHistory)

不积跬步无以至千里 流量使用情况,好多软件都会带这个功能,比如360的流量监控,好多之类的,手机管家都会带上这个流量计算的功能,连系统应用设置里面也会带一个流量使用情况的查看功能,为什么呢?因为流量的使用关乎到用户使用流量的计费,当流量使用了很多,会给用…

vnstat流量统计(2.8版本)

vnstat流量统计&#xff08;2.8版本&#xff09; vnStat 是一个基于控制台的 Linux 和 BSD 网络流量监视器&#xff0c;它为所选接口保留网络流量日志。它使用内核提供的网络接口统计信息作为信息源。这意味着 vnStat 实际上不会嗅探任何流量&#xff0c;并且无论网络流量率如…

中职流量包分析attack/capture(1)

我希望网络安全的世界大家可以贡献自己的一部分&#xff0c;而不是拿来自私自利 作者拿到的流量包和题目是有出入的&#xff0c;但是因为出的题大同小异所以能分析出来 attack 1. 分 析 attack.pcapng 数 据 包 文 件 &#xff0c;通 过 分 析数据 包 attack.pcapng 找出恶意…

抓包部分软件时无网络+过代理检测 解决办法 安卓黄鸟httpcanary+vmos

解决软件抓包时无网络和代理检测&#x1f680; 需要准备的工具&#xff1a; 安卓手机 vmos pro 需要抓包的软件 第一步&#xff1a;下载好相应版的本的vmos room 第二步&#xff1a;文件中转站->我要导入->导入对应真机需要抓包APP 第三步&#xff1a;测试软件在vmos…

测试apk-异常管控NetTraffic攻击者开发

1. 目的 基于《软件绿色联盟应用体验标准》中 NetTraffic 资源的定义&#xff0c;对 NetTraffic 后台多次小流量数据包的行为模拟。旨在触发手机中异常功耗管控机制。 本次灭屏NetTraffic使用次数至少超过的二个等级:30次,60次&#xff0c;执行如下判断&#xff1a; 绿线不管控…

雷电模拟器无法修改网络,没有出现修改网络的选项,导致fiddler无法连接

对于一个小白来说&#xff0c;可能这就能耗掉一个下午的时间了&#xff0c;比如我&#xff0c;&#xff0c;&#xff0c;&#xff0c;要命的是这种问题对于绝大多数小白还完全不是问题&#xff0c;所以找了很久都没有解决答案&#xff0c;所以我是。。小白中的小白。。 模拟器…

TrackingNet上进行评估

TrackingNet上进行评估 说明&#xff1a;在目标跟踪测试数据集中&#xff0c;在TrackingNet和GOT-10K上的评估结果需要通过在线评估的方式获取。 website&#xff1a;Welcome - EvalAI 自行注册账户&#xff0c;注册好后按照以下操作就可以进行评估了。 在All Changes中找到…

ARP欺骗攻击(流量图片)——dsniff与driftnet使用

ARP欺骗攻击&#xff08;流量&图片&#xff09; 原理&#xff1a; 首先我们![请添加图片描述](https://img-blog.csdnimg.cn/7de7923387224bcda1ea4be958032ae9.png 要明白何为ARP&#xff08;地址解析协议&#xff09;&#xff1a;是根据 IP地址 获取 物理地址 的一个 TC…

Google pixel 原生安卓出现 WiFi 网络受限、优化网速、网络无法连接问题

谷歌从 Android 5.0 开始就引入了「Captive Portal」机制&#xff0c;主要用来检测 WiFI 网络认证是否正常&#xff0c;默认检测访问的是谷歌服务器。 众所周知谷歌服务器是需要404工具才能正常访问&#xff0c;所以如果你没有404工具的情况下&#xff0c;WiFi 就会出现网络受…

悉尼科技大学计算机专业就业,悉尼科技大学计算机专业怎么样

悉尼科技大学计算机科学是一门包含各种各样与计算和信息处理相关主题的系统学科&#xff0c;从抽象的算法分析、形式化语法等等&#xff0c;到更具体的主题如编程语言、程序设计、软件和硬件等。信息化产业的今天&#xff0c;这类专业的重要性也愈加显现。悉尼科技大学的互联网…