Gin中间件函数原理

在Gin框架中,Context.Next() 方法是中间件处理的核心,它控制着请求处理链(HandlersChain)中的执行流。下面是对这个函数及相关概念的详细解释:

func (c *Context) Next()
这个方法定义在 Context 结构体上,用于在中间件中调用,以便继续执行下一个中间件或处理函数。

type Context struct {writermem responseWriterRequest   *http.RequestWriter    ResponseWriterParams   Paramshandlers HandlersChain   //index    int8fullPath stringengine       *Engineparams       *ParamsskippedNodes *[]skippedNode...
}func (c *Context) Next() {c.index++for c.index < int8(len(c.handlers)) {c.handlers[c.index](c)c.index++}
}

增加 index:每次调用 Next() 时,首先将 c.index 增加1。c.index 是一个记录当前正在执行的中间件位置的计数器。当一个中间件或处理函数调用 Next(),index 就会递增,指向下一个要执行的中间件或处理函数。

执行循环:循环会继续执行,只要 index 小于 handlers 列表的长度。handlers 是一个类型为 HandlersChain 的切片,存储了所有注册到当前路由的中间件和处理函数。

调用处理函数:在循环中,通过 c.handlers [c.index] ( c ) 调用当前 index 指向的处理函数,这里的 c 是当前的 Context 实例。每次函数调用后,index 再次递增,准备调用下一个处理函数。

HandlersChain 和 gin.HandlerFunc 以函数传递机制

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)// HandlersChain defines a HandlerFunc slice.
type HandlersChain []HandlerFunc// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

在Gin中:

HandlersChain:这是一个由 gin.HandlerFunc 构成的切片(slice),即 []gin.HandlerFunc。它用于存储为特定路由注册的所有处理函数,包括中间件和终结点处理函数。

gin.HandlerFunc:这是定义为 func(*gin.Context) 的类型。所有处理HTTP请求的函数,无论是中间件还是最终的响应处理函数,都必须符合这个函数签名。

解析 c.handlers[c.index]
当代码执行到 c.handlers[c.index] 时,这里发生的是:

访问切片元素:c.handlers 是一个 HandlersChain,即 []gin.HandlerFunc。通过 c.index,我们访问这个切片的一个具体元素,这个元素是一个 gin.HandlerFunc。

执行函数:所获取的 gin.HandlerFunc 通过 c.handlers [c.index] ( c ) 被执行。这里,c 是当前的 *gin.Context 实例,作为参数传递给 gin.HandlerFunc。

函数执行机制
传递 *gin.Context:每个 gin.HandlerFunc 都接收一个 *gin.Context 作为参数。这样,无论是中间件还是路由处理函数,都可以通过这个上下文操作请求数据、修改响应或控制请求流程(如中断请求)。

递归调用 Next():在一些中间件或处理函数中,可以选择调用 c.Next() 来继续执行后续的处理链。如果这个调用存在,那么 Next() 中的循环将继续执行下一个处理函数,直到所有的函数都执行完毕。

例子和上下文管理
假设你有如下的中间件和处理函数定义:

func MiddlewareA(c *gin.Context) {fmt.Println("Before A")c.Next()fmt.Println("After A")
}func MiddlewareB(c *gin.Context) {fmt.Println("Before B")c.Next()fmt.Println("After B")
}func FinalHandler(c *gin.Context) {fmt.Println("Final Handler Reached")
}

如果你将这些函数注册到一个路由:

router.GET("/example", MiddlewareA, MiddlewareB, FinalHandler)

执行顺序将是:

打印 “Before A”
打印 “Before B”
打印 “Final Handler Reached”
打印 “After B”
打印 “After A”
这种执行顺序体现了 Next() 的工作方式和中间件的前置后置逻辑的组合使用。

为什么中间函数需要直接定义 func(c *gin.Context),或者通过工厂函数返回 gin.HandlerFunc

在Gin框架中,当我们讨论中间件或处理函数时,这些函数通常直接定义为符合 gin.HandlerFunc 类型的函数,或者是返回 gin.HandlerFunc 类型的函数(工厂函数)。让我们来详细解释这两种情况下 c.handlers[c.index] 的行为和执行逻辑。

  1. 直接定义为 gin.HandlerFunc

在最常见的情况下,中间件或处理函数被直接定义为 gin.HandlerFunc 类型,这意味着它们是这样的函数:

func someMiddleware(c *gin.Context) {// do somethingc.Next()
}

这种情况下,c.handlers 数组直接包含了这些中间件和处理函数的引用。当执行 c.handlers[c.index] ( c) 时,它直接调用数组中存储的函数,并将当前的 *gin.Context 实例 c 作为参数传递给这个函数。

  1. 通过工厂函数返回 gin.HandlerFunc

另一种情况是中间件或处理函数通过一个工厂函数来生成。工厂函数的形式通常是这样:

func createMiddleware(config SomeConfig) gin.HandlerFunc {return func(c *gin.Context) {// use configc.Next()}
}

在这种情况下,工厂函数 createMiddleware 在被调用时返回一个 gin.HandlerFunc,这个返回的函数才是实际被添加到 c.handlers 数组中的中间件。例如,你可能在路由设置时这样使用它:

router.GET("/example", createMiddleware(someConfig), someHandler)

此时,createMiddleware(someConfig) 调用结果(一个 gin.HandlerFunc)被添加到处理链中。当请求到来时,通过 c.handlers[c.index] ( c) 调用,它执行的是 createMiddleware 返回的那个具体函数。

执行流程解析
在任何情况下,不论是直接定义的 gin.HandlerFunc 还是通过工厂函数返回的 gin.HandlerFunc,一旦这些函数被添加到 c.handlers 数组中:

函数调用:c.handlersc.index 直接调用这些函数,传递 *gin.Context 实例作为参数。
执行逻辑:无论是直接定义的函数还是通过工厂函数创建的函数,它们在被调用时都接收同样的 *gin.Context 参数,执行定义在函数内的逻辑。

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

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

相关文章

MYSQL执行过程和顺序详解

一、前言 1.1、说明 就MySQL在执行过程、sql执行顺序&#xff0c;以及一些相关关键字的注意点方面的学习分享内容。 在参考文章的基础上&#xff0c;会增加自己的理解、看法&#xff0c;希望本文章能够在您的学习中提供帮助。 如有错误的地方&#xff0c;欢迎指出纠错&…

AdaBoost 算法

目录 什么是 AdaBoost 算法? Adaboost 的 7 个优缺点 集成学习:人多力量大: Bagging:民主。Boosting :挑选精英。长短期记忆网络:引入遗忘机制 生成对抗网络 :物竞天择适者生存 首先,了解一下集成学习及 Boosting 算法 集成学习归属于机器学习,他是一种「训练思路…

Project Euler_Problem 159_Digital Root Sums of Factorisations

原题目&#xff1a; 解题思路&#xff1a; 代码&#xff1a; void solve() {ll i, j,k,x,y,z,p,q,u,v;N 1000000, NN 1024;//N 20;double a, b, c,d;M.NT.get_prime_Euler(2000000);for (i 2; i < N; i) {x (i-1)%91;for (j 2; j<sqrt(i); j) {if (i % j 0) {x …

SynchronizedMap 和 ConcurrentHashMap 有什么区别

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:SynchronizedMap 和 ConcurrentHashMap 有什么区别 锁的粒度:SynchronizedMap 使用全局锁,而 ConcurrentHashMap 使用锁分离技术,每个段有自己的…

宝妈如何在家创造收入?五种兼职工作让你轻松赚钱!

许多宝妈为了陪伴孩子成长&#xff0c;毅然选择了全职妈妈的角色&#xff0c;然而&#xff0c;她们内心仍希望能有一份收入&#xff0c;实现经济独立。于是&#xff0c;寻找既能照顾家庭又能赚钱的工作成了她们的迫切需求。 然而&#xff0c;这样的需求也往往让宝妈们成为一些…

WLAN故障处理

目录 一.wlan基础知识 1.wlan是什么 2.WLAN配置步骤 &#xff08;1&#xff09;AP上线 &#xff08;2&#xff09;业务配置 二.WLAN故障处理一般步骤 1.评估故障严重程度 2.收集信息填写故障报告 &#xff08;1&#xff09;组网信息 (2)运行状态 &#xff08;3&#…

Linux三剑客-sed、awk、egrep(上)

一、知识梗概 二、正则表达式 定义&#xff1a;正则表达式是一种强大的文本处理工具&#xff0c;用于在文本中搜索符合特定模式的字符串。它由一系列特殊字符和普通字符组成&#xff0c;可以定义复杂的搜索模式。正则表达式被广泛应用于各种编程语言和文本处理工具中。 简单来…

antDesignVue 使用-持续更新

背景 vue3viteantdesignvuevue-router 1,全局完整注册 1.1下载antdesignvue npm i --save ant-design-vue 或者 npm install ant-design-vuenext --save 1.2在mian.ts中引入 import { createApp } from vue import { createPinia } from piniaimport App from ./App.vue …

微信跳转页面时发生报错

报错如下图所示&#xff1a; 解决方法&#xff1a;&#xff08;从下面四种跳转方式中任选一种&#xff0c;哪种能实现效果就用哪个&#xff09; 带历史回退 wx.navigateTo() //不能跳转到tabbar页面 不带历史回退 wx.redirectTo() //跳转到另一个页面wx.switchTab() //只能…

读书笔记:高效能人士的七个习惯

前言 恐惧感和不安全感 现代社会&#xff0c;太多的人饱受恐惧感的折磨。他们恐惧将来&#xff0c;恐惧失业&#xff0c;恐惧无力养家。这种弱点&#xff0c;常常助长了一种倾向&#xff1a;无论在工作时&#xff0c;还是回到家中&#xff0c;都倾向于零风险的生活&#xff0…

MathType2024中文网站7.9最新版本数学公式编辑器下载

MathType是一款专业的数学公式编辑器&#xff0c;由Design Science公司开发。它为用户提供了一个便捷的方式来创建和编辑复杂的数学公式&#xff0c;适用于各种文档和出版物。MathType与常见的文字处理软件和演示程序配合使用&#xff0c;能够在各种文档中加入复杂的数学公式&a…

【MYSQL】MySQL整体结构

无论你是前端还是后端&#xff0c;只要是一个合格的开发者&#xff0c;对于MySQL这个名词相信都不陌生&#xff0c;MySQL逐渐成为了最受欢迎的关系型数据库&#xff0c;无论你是大前端&#xff0c;亦或是Java、Go、Python、C/C、PHP....等这些语言的程序员&#xff0c;对于MySQ…

Linux下SPI驱动:SPI主机驱动简介

一. 简介 SPI 驱动框架和 I2C 很类似&#xff0c;都分为主机控制器驱动和设备驱动&#xff0c;主机控制器也就是 SOC的 SPI 控制器接口。 例如&#xff0c;在裸机篇中的《第二十七章 SPI 实验》&#xff0c;我们编写了 bsp_spi.c 和 bsp_spi.h 这两个文件&#xff0c;这…

Java类与对象:面向对象编程的基石

Java类与对象&#xff1a;面向对象编程的基石 1. 类与对象的概念2. 类的创建与使用3. 对象的创建与使用4. 类与对象的关系5. 封装与继承6. 示例代码解析7. 总结 在Java编程中&#xff0c;类与对象是面向对象编程的基础&#xff0c;它们为我们提供了一种抽象和封装的方法来描述现…

【JavaScript】ECMAScript/DOM/BOM

JavaScript介绍 Web早期&#xff0c;客户端校验网页表单会频繁地与服务端进行通信而消耗大量的网络资源&#xff0c;在网速本就很慢的时代&#xff0c;这十分影响用户交互体验。为了解决这一问题&#xff0c;网景作为当时引领技术革新的公司&#xff0c;计划为客户端开发一个脚…

vulhub靶场shiro系列漏洞复现CVE-2010-3863、CVE-2016-4437(shiro550)、CVE-2020-1957、shiro721

目录 shiro简介 shiro漏洞成因 shiro550 shiro721 利用过程 CVE-2010-3863&#xff08;未授权访问&#xff09; 简介 CVE-2016-4437(shiro550) 简介 CVE-2020-1957&#xff08;未授权访问&#xff09; 漏洞影响 简介 url处理过程 shiro721 影响版本 简介 利用 …

ON1 NoNoise AI 2024 for Mac/Win:智能降噪,重塑影像之美

在数字摄影领域&#xff0c;图片质量往往受到多种因素的影响&#xff0c;其中噪点问题尤为突出。ON1 NoNoise AI 2024作为一款专为Mac和Windows平台打造的AI图片降噪工具&#xff0c;凭借其卓越的降噪性能和智能化的操作体验&#xff0c;成为了摄影师和图像处理专家们的首选工具…

bugku-web-decrypt

这里的提示解密后没有什么意义 这里下载文件包 得到一个index.php文件 得到代码 <?php function encrypt($data,$key) {$key md5(ISCC);$x 0;$len strlen($data);$klen strlen($key);for ($i0; $i < $len; $i) { if ($x $klen){$x 0;}$char . $key[$x];$x1;}for…

2023androidstudio

终于下定决心将studio升级到新版本使用了&#xff0c;在这总结下和之前的差别 问题一&#xff1a; 创建java类型的项目 在新版本studio中&#xff0c;创建android项目时&#xff0c;语言选择中没有java选项了&#xff0c;这让一直使用java开发的我摸索了好久&#xff0c;终于…

Elasticsearch 支持的插件 —— 筑梦之路

Analysis 插件&#xff1a; 1、IK Analyzer&#xff1a;适用于中文分词的插件&#xff0c;提供了针对中文文本的分析器。 2、Smart Chinese Analysis&#xff1a;另一个中文分词插件&#xff0c;支持中文智能分词。 集群管理插件&#xff1a; 1、Kibana&#xff1a;Elasticsear…