Gin框架操作指南07:路由与中间件

官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/
注:本教程采用工作区机制,所以一个项目下载了Gin框架,其余项目就无需重复下载,想了解的读者可阅读第一节:Gin操作指南:开山篇。
本节演示路由与中间件,包括路由参数;路由组;使用中间件;在中间件中使用Goroutine;自定义中间件。其中不使用默认的中间件很简单,就是使用
r := gin.New()代替r := gin.Default(),读者可自行演示。在开始之前,我们需要在”03路由与中间件“目录下打开命令行,执行如下命令来创建子目录:

mkdir 路由参数 路由组 使用中间件 在中间件中使用Goroutine 自定义中间件

目录

    • 一、路由参数
    • 二、路由组
    • 三、使用中间件
    • 四、在中间件中使用Goroutine
    • 五、自定义中间件

一、路由参数

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 创建 Gin 路由实例router := gin.Default()// 路由匹配模式为 /user/:name// ":name" 是路由参数,可以匹配具体的用户名,例如 /user/john// 此 handler 将匹配像 /user/john 这样的 URL,但是不会匹配 /user/ 或者 /userrouter.GET("/user/:name", func(c *gin.Context) {// 使用 c.Param 获取路由中的参数 "name"name := c.Param("name")// 返回包含该 name 的字符串作为响应c.String(http.StatusOK, "Hello %s", name)})// 路由匹配模式为 /user/:name/*action// ":name" 是路由参数,可以匹配具体的用户名,例如 /user/john// "*action" 是通配符参数,表示匹配从指定路径开始的所有路径片段,例如 /user/john/send 或 /user/john/anything_else// 如果路径为 /user/john 并且没有其他路由匹配,Gin 会自动将其重定向到 /user/john/router.GET("/user/:name/*action", func(c *gin.Context) {// 获取路由参数 "name" 的值name := c.Param("name")// 获取通配符参数 "action" 的值,该值匹配路径中 "name" 后面的所有部分action := c.Param("action")// 拼接 name 和 action 作为响应的消息message := name + " is " + action// 返回拼接后的消息作为响应c.String(http.StatusOK, message)})// 启动 HTTP 服务器,监听 8080 端口router.Run(":8080")
}

效果
在这里插入图片描述

二、路由组

package mainimport ("net/http""github.com/gin-gonic/gin"
)// loginEndpoint 处理登录请求的示例处理函数
func loginEndpoint(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Login successful"})
}// submitEndpoint 处理提交请求的示例处理函数
func submitEndpoint(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Submit successful"})
}// readEndpoint 处理读取请求的示例处理函数
func readEndpoint(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Read successful"})
}func main() {// 创建一个默认的 Gin 路由器router := gin.Default()// 定义第一个路由组 "v1"。所有 v1 组中的路由将以 "/v1" 开头v1 := router.Group("/v1"){// v1 组下的 POST 请求路由,处理 /v1/login,调用 loginEndpoint 处理函数v1.POST("/login", loginEndpoint)// v1 组下的 POST 请求路由,处理 /v1/submit,调用 submitEndpoint 处理函数v1.POST("/submit", submitEndpoint)// v1 组下的 POST 请求路由,处理 /v1/read,调用 readEndpoint 处理函数v1.POST("/read", readEndpoint)}// 定义第二个路由组 "v2"。所有 v2 组中的路由将以 "/v2" 开头v2 := router.Group("/v2"){// v2 组下的 POST 请求路由,处理 /v2/login,调用 loginEndpoint 处理函数v2.POST("/login", loginEndpoint)// v2 组下的 POST 请求路由,处理 /v2/submit,调用 submitEndpoint 处理函数v2.POST("/submit", submitEndpoint)// v2 组下的 POST 请求路由,处理 /v2/read,调用 readEndpoint 处理函数v2.POST("/read", readEndpoint)}// 启动 HTTP 服务器,监听 8080 端口router.Run(":8080")
}

效果
在这里插入图片描述
在这里插入图片描述

三、使用中间件

package mainimport ("log""time""github.com/gin-gonic/gin"
)// MyBenchLogger 是自定义的中间件,用于在路由上输出耗时信息
func MyBenchLogger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()// 继续处理请求c.Next()// 处理结束后,计算请求的耗时并输出日志latency := time.Since(t)log.Print(latency)}
}// AuthRequired 是模拟的中间件,通常用于验证用户是否通过身份认证
func AuthRequired() gin.HandlerFunc {return func(c *gin.Context) {// 这里可以编写检查用户身份的逻辑// 如果用户未通过身份验证,可以使用 `c.Abort()` 停止请求处理链log.Println("AuthRequired middleware executed")// 继续处理请求c.Next()}
}// 模拟的处理器函数
func benchEndpoint(c *gin.Context) {// 这是实际的处理逻辑,返回一个简单的文本响应c.String(200, "Benchmark endpoint")
}func loginEndpoint(c *gin.Context) {// 登录处理逻辑,返回一个简单的文本响应c.String(200, "Login successful")
}func submitEndpoint(c *gin.Context) {// 表单提交处理逻辑,返回一个简单的文本响应c.String(200, "Form submitted")
}func readEndpoint(c *gin.Context) {// 数据读取处理逻辑,返回一个简单的文本响应c.String(200, "Data read")
}func analyticsEndpoint(c *gin.Context) {// 嵌套路由组处理逻辑,用于处理特定功能,例如数据分析c.String(200, "Analytics data")
}func main() {// 新建一个没有任何默认中间件的路由r := gin.New()// 全局中间件// Logger 中间件会记录请求的日志,写入 gin.DefaultWriter (默认是 os.Stdout)r.Use(gin.Logger())// Recovery 中间件会自动捕获请求中的 panic,并返回 500 错误r.Use(gin.Recovery())// 可以为特定路由使用中间件,这里为 "/benchmark" 路由添加了自定义的 MyBenchLogger 中间件r.GET("/benchmark", MyBenchLogger(), benchEndpoint)// 认证路由组 authorized,通过 AuthRequired 中间件来控制访问权限authorized := r.Group("/")// 使用自定义的 AuthRequired 中间件来保护这个路由组authorized.Use(AuthRequired()){// 这些路由都属于 authorized 路由组,并且会执行 AuthRequired 中间件authorized.POST("/login", loginEndpoint)authorized.POST("/submit", submitEndpoint)authorized.POST("/read", readEndpoint)// 嵌套路由组 testing,所有在此路由组下的路由也会执行 AuthRequired 中间件testing := authorized.Group("testing")testing.GET("/analytics", analyticsEndpoint)}// 启动 HTTP 服务,监听端口 8080r.Run(":8080")
}

GET效果
在这里插入图片描述
在这里插入图片描述

POST效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、在中间件中使用Goroutine

package mainimport ("log""time""github.com/gin-gonic/gin"
)func main() {// 初始化 Gin 默认实例,它包含了 Logger 和 Recovery 中间件r := gin.Default()// 异步处理r.GET("/long_async", func(c *gin.Context) {// 创建在 goroutine 中使用的副本// 由于上下文在 Goroutine 中被使用,必须通过 c.Copy() 拷贝一份上下文的副本。// 原因是 Gin 的上下文是有状态的,多 Goroutine 并发访问时不能共享原始上下文。cCp := c.Copy()// 启动 Goroutine 以模拟长任务go func() {// 用 time.Sleep 模拟一个耗时任务,执行 5 秒。time.Sleep(5 * time.Second)// 使用副本上下文来访问请求的路径信息// 如果直接使用原始上下文,可能会导致并发问题。log.Println("Done! in path " + cCp.Request.URL.Path)}()})// 同步处理r.GET("/long_sync", func(c *gin.Context) {// 同步处理时,没有 Goroutine,所以可以直接使用原始上下文。// 用 time.Sleep 模拟一个长任务,执行 5 秒。time.Sleep(5 * time.Second)// 输出请求路径log.Println("Done! in path " + c.Request.URL.Path)})// 启动服务器,监听在 0.0.0.0:8080r.Run(":8080")
}

打开浏览器
访问 http://localhost:8080/long_async 来测试异步处理,浏览器/Postman 会立即返回响应,不会等到 5 秒任务完成。控制台在 5 秒后会输出 Done! in path /long_async
在这里插入图片描述

访问 http://localhost:8080/long_sync 来测试同步处理。浏览器/Postman 会等到 5 秒任务完成后再返回响应。控制台会立即输出 Done! in path /long_sync
在这里插入图片描述

五、自定义中间件

package mainimport ("log""time""github.com/gin-gonic/gin"
)// Logger 自定义中间件,用于记录请求的延迟和状态
func Logger() gin.HandlerFunc {return func(c *gin.Context) {// 记录当前时间,用于计算请求延迟t := time.Now()// 设置一个名为 "example" 的上下文变量,其值为 "12345"c.Set("example", "12345")// 请求前的操作可以在这里进行// 例如:记录请求开始时间或执行一些检查// 处理请求,调用后续的处理函数c.Next()// 请求后的操作可以在这里进行// 计算请求处理的延迟latency := time.Since(t)// 打印延迟信息到日志log.Print(latency)// 获取并打印响应状态码status := c.Writer.Status()log.Println(status)}
}func main() {// 创建一个新的 Gin 实例,没有默认中间件r := gin.New()// 使用自定义的 Logger 中间件r.Use(Logger())// 定义一个 GET 路由 /testr.GET("/test", func(c *gin.Context) {// 从上下文中获取 "example" 变量,并进行类型断言example := c.MustGet("example").(string)// 打印获取到的 "example" 变量值:12345log.Println(example)})// 启动服务器,监听在 0.0.0.0:8080r.Run(":8080")
}

效果
在这里插入图片描述

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

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

相关文章

【JVM】内存模型

文章目录 内存模型的基本概念案例 程序计数器栈Java虚拟机栈局部变量表栈帧中局部变量表的实际状态栈帧中存放的数据有哪些 操作数栈帧数据 本地方法栈 堆堆空间是如何进行管理的? 方法区静态变量存储 直接内存直接内存的作用 内存模型的基本概念 在前面的学习中,我们知道了字…

Java 8 Stream API:从基础到高级,掌握流处理的艺术

一、Stream(流)基本介绍 Java 8 API 添加了一个新的抽象称为Stream(流),可以让你以一种声明的方式处理数据,这种风格将要处理的元素集合看做一种流,元素流在管道中传输,并在管道中间…

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统,功能带有卡密生成和添加黑名单等,源码放在我的网盘里已经两年之久,由于玖逸现在已经跑路了所以现在发出来分享给大家,需要的可以自己拿去而开,反正功能也不是很多具体的自己…

电脑视频剪辑大比拼,谁更胜一筹?

随着短视频的火爆,越来越多的人开始尝试自己动手制作视频,无论是记录生活点滴还是创作个性短片,一款好用的视频剪辑软件是必不可少的。今天,我们就从短视频运营的角度,来聊聊几款热门的电脑视频剪辑软件,看…

docker配置加速器

阿里云 控制台》容器镜像服务》镜像工具》镜像加速器 复制地址:https://ywtoq7bz.mirror.aliyuncs.com 到:etc/docker下:vi daemon.json 格式: { "registry-mirrors": ["加速器地址"] } 注&#xff1…

JavaScript:闭包、防抖与节流

一,闭包 1,什么是闭包 闭包是指一个函数和其周围的词法环境(lexical environment)的组合。 换句话说,闭包允许一个函数访问并操作函数外部的变量。 闭包的核心特性: 函数内部可以访问外部函数的变量即使外部函数已经返回,内部…

一款新开源跨平台的.NET Word(docx)模版导出引擎,完美支持Linux和Mac操作系统(附源码)

前言 在数字化办公日益盛行的今天,文档处理成为了我们日常工作不可或缺的一部分。然而,许多传统的文档处理工具都依赖于特定的操作系统和复杂的组件安装,这无疑给跨平台办公带来了诸多不便。为了解决这一问题,我们找到了一个新的…

【MR开发】在Pico设备上接入MRTK3(一)——在Unity工程中导入MRTK3依赖

写在前面的话 在Pico上接入MRTK3,目前已有大佬开源。 https://github.com/Phantomxm2021/PicoMRTK3 也有值得推荐的文章。 MRTK3在PICO4上的使用小结 但由于在MacOS上使用MRTK3,无法通过Mixed Reality Feature Tool工具管理MRTK3安装包。 故记录一下…

◇【论文_20151120_20160405v3】Dueling Network 决斗〔Google DeepMind〕

整理代码:Dueling_DQN__Pendulum_v1.ipynb https://arxiv.org/abs/1511.06581 Dueling Network Architectures for Deep Reinforcement Learning 文章目录 摘要1. 引言1.1. 相关工作 2. 背景2.1. Deep Q-networks 【DQN】2.2. Double Deep Q-networks 【DDQN】2.3…

OpenCV高级图形用户界面(13)选择图像中的一个矩形区域的函数selectROI()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 允许用户在给定的图像上选择一个感兴趣区域(ROI)。 该功能创建一个窗口,并允许用户使用鼠标来选择一个 ROI。…

其他css的用途

1.animation-fill-mode: backwards; //避免了在动画开始前元素的突然显现,动画必要。 2.用rem响应式字体大小,可以在html样式定义font-size?(例10px,62.5%(100%是16px))。然后样式就可以用rem代替px。 3.color: transparent;: 这行代码将文…

计算生物学与生物信息学漫谈-2-测序深度/读长质量和Fasta处理

上一篇文章中我们介绍了测序技术的由来与发展,那么在介绍第三代测序的时候,我们提到了关于测序深度和读长的问题,那么本篇文章就详解介绍一下。 计算生物学与生物信息学漫谈-1-测序一路走来-CSDN博客 目录 1.测序深度SEQUENCING DEPTH &…

《AI生成式工具使用》之:自助生成视频

目录 背景说明及目标: 实现过程: 1、有问题找度娘 2、利用剪映AI生成视频具体步骤 剪映AI感受 3、利用万彩AI生成视频具体步骤 万彩AI感受 4、利用腾讯云剪生成视频具体步骤 腾讯云剪感受 最终结论: 关注我,躺不平就一起…

【部署篇】RabbitMq-02单机模式部署

RabbitMQ和Erlang/OTP兼容性矩阵 下表提供了当前支持的RabbitMQ版本系列的Erlang兼容性矩阵。更多RabbitMQ版本,请参阅官网的系列兼容性列表。官网地址:https://www.rabbitmq.com/docs/which-erlang RabbitMQ版本最小支持版本最大支持版本备注 4.0.24.…

Axure重要元件三——中继器添加数据

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 本节课:中继器添加数据 课程内容:添加数据项、自动添加序号、自动添加数据汇总 应用场景:表单数据的添加 案例展示: 步骤…

经验是最坏的老师

奥斯卡.王尔德说过:经验是最坏的老师。他经常先考试,然后再给出指导。 这让我想起了另外一句话:愚笨的人,往往都在犯同样的错误;普通的人,从自己的错误中学习;聪明人从别人的错误中学习。 如果…

Linux 防火墙的开启、关闭、禁用命令

Linux 防火墙的开启、关闭、禁用命令 文章目录 Linux 防火墙的开启、关闭、禁用命令1.设置开机启用防火墙2.设置开机禁用防火墙3.启动防火墙4.关闭防火墙5.检查防火墙状态 1.设置开机启用防火墙 systemctl enable firewalld.service2.设置开机禁用防火墙 systemctl disable f…

006、链表分割

0、题目描述 链表分割 这道题的思路,遍历原链表,小于x的放到一个链表里,大于x的放到另一个链表里。然后把两个链表接起来。 建立的两个新链表都是有哨兵位的,也就是有头结点,排序结束后要free两个头结点。 1、法1 还…

CSS3 提示框带边角popover

CSS3 提示框带边角popover。因为需要绝对定位子元素&#xff08;这里就是伪元素&#xff09;&#xff0c;所以需要将其设置为相对对位 <!DOCTYPE html> <html> <head> <title>test1.html</title> <meta name"keywords" con…

格点拉格朗日插值与PME算法

技术背景 在前面的一篇博客中&#xff0c;我们介绍了拉格朗日插值法的基本由来和表示形式。这里我们要介绍一种拉格朗日插值法的应用场景&#xff1a;格点拉格朗日插值法。这种场景的优势在于&#xff0c;如果我们要对整个实数空间进行求和或者积分&#xff0c;计算量是随着变量…