当前位置: 首页 > 编程日记 > 正文

Gin源码解析和例子——中间件(middleware)

在《Gin源码解析和例子——路由》一文中,我们已经初识中间件。本文将继续探讨这个技术。(转载请指明出于breaksoftware的csdn博客)

Gin的中间件,本质是一个匿名回调函数。这和绑定到一个路径下的处理函数本质是一样的。

再以Engine的Default方法为例

func Default() *Engine {debugPrintWARNINGDefault()engine := New()engine.Use(Logger(), Recovery())return engine
}

第4行就让该Engine使用了Logger和Revoery两个中间件。Use方法将新增的中间件加入到中间件集合中

// Use adds middleware to the group, see example code in github.
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {group.Handlers = append(group.Handlers, middleware...)return group.returnObj()
}

因为是append,所以后加入的中间件排在集合后面。理解这个特性对我们正确使用中间件很重要。

再回顾下之前介绍的路由的代码

	r := gin.Default()// Ping testr.GET("/ping", func(c *gin.Context) {c.String(http.StatusOK, "pong")})

host:port/ping下的请求,将被路由到输出pong的匿名函数里。GET方法封装了handle方法

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

这儿注意下第3行,上面这个匿名函数似乎是和其他匿名函数合并成一个匿名函数集合。然后再在第4行和绝对路径绑定。

func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {finalSize := len(group.Handlers) + len(handlers)if finalSize >= int(abortIndex) {panic("too many handlers")}mergedHandlers := make(HandlersChain, finalSize)copy(mergedHandlers, group.Handlers)copy(mergedHandlers[len(group.Handlers):], handlers)return mergedHandlers
}

这儿合并的就是中间件集合(group.Handlers)。第7~8行代码,告诉我们中间件的回调要先于用户定义的路径处理函数。那么上例中,mergeHandlers中的成员是【logger回调,recovery回调,GET的匿名回调】。

这样,每个路径的回调函数链都将包含中间件的回调,即【logger回调,recovery回调】。

我再看一个最简单的中间件的实现

func MiddlewareDemo() gin.HandlerFunc {return func(c *gin.Context) {c.Next()}
}

这个中间件只是返回了一个匿名函数,该函数内部需要调用Conext的Next函数来驱动执行之后的handler。

func (c *Context) Next() {c.index++for s := int8(len(c.handlers)); c.index < s; c.index++ {c.handlers[c.index](c)}
}

这也是Gin设计中比较奇葩的地方:

  • Context的Next方法让合并之后的handlers中的回调执行
  • handlers中的回调调用Context的Next方法以驱动下个回调执行

如果我们不看Next的实现,单从上面的话中可以感觉到似乎逻辑进入了一种异常循环的状态。其实Gin使用了一个Context中的index变量来解决了这个问题。于是中间件、框架和路径对应的回调之前的关系是

我们看个例子

package mainimport ("log""net/http""github.com/gin-gonic/gin"
)func MiddlewareA() gin.HandlerFunc {return func(c *gin.Context) {log.Println("MiddlewareA before request")// before requestc.Next()// after requestlog.Println("MiddlewareA after request")}
}func MiddlewareB() gin.HandlerFunc {return func(c *gin.Context) {log.Println("MiddlewareB before request")// before requestc.Next()// after requestlog.Println("MiddlewareB after request")}
}// This function's name is a must. App Engine uses it to drive the requests properly.
func main() {// Starts a new Gin instance with no middle-warer := gin.New()r.Use(MiddlewareA(), MiddlewareB())r.GET("/ping", func(c *gin.Context) {c.String(http.StatusOK, "pong")log.Println("pong")})r.Run(":8080")
}

触发一次请求后,服务器的日志输出是

2018/12/03 16:07:30 MiddlewareA before request
2018/12/03 16:07:30 MiddlewareB before request
2018/12/03 16:07:30 pong
2018/12/03 16:07:30 MiddlewareB after request
2018/12/03 16:07:30 MiddlewareA after request

可以看到,结果符合我们对代码的解读。

相关文章:

DNS简单配置

DNS的原理就不说了&#xff0c;这里只是做个简单的配置&#xff0c;也是方便自己记忆&#xff0c;在这里还要十分感谢redking老大的教程&#xff01;要安装的bind* 、caching-nameserver 包1、/var/named/chroot/etc/named.conf这个文件需要自己创建options { listen-on…

关系抽取论文整理,核方法、远程监督的重点都在这里

来源 | CSDN 博客作者 | Matt_sh&#xff0c;编辑 | Carol来源 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;本文是个人阅读文章的笔记整理&#xff0c;没有涉及到深度学习在关系抽取中的应用。笔记中一部分来自个人解读&#xff0c;一部分来自原文&#xff0…

freemarker内建函数介绍

Sequence的内置函数1.sequence?first 返回sequence的第一个值。2.sequence?last 返回sequence的最后一个值。3.sequence?reverse 将sequence的现有顺序反转&#xff0c;即倒序排序4.sequence?size 返回sequence的大小5.sequence?sort 将sequence中的对象转化为字符串后顺序…

PowerBuilder 11.x 的重要进步和不足

PowerBuilder 11&#xff08;以下简称PB&#xff09;出来有一段时间了&#xff0c;但很多用户对PB11的到底有哪些进步还不是很清楚&#xff0c;由于对PB11缺乏了解和信心&#xff0c;目前用PB11做出像样应用的用户不多&#xff0c;这确实非常遗憾&#xff0c;这里我讲一下我对P…

超赞的PyTorch资源大列表,GitHub标星9k+,中文版也上线了

点击阅读原文&#xff0c;快速报名&#xff01;作者 | 红色石头来源 | AI有道&#xff08;ID: redstonewill&#xff09;自 2017 年 1 月 PyTorch 推出以来&#xff0c;其热度持续上升。PyTorch 能在短时间内被众多研究人员和工程师接受并推崇是因为其有着诸多优点&#xff0c;…

C++拾取——Linux下实测布隆过滤器(Bloom filter)和unordered_multiset查询效率

布隆过滤器是一种判定元素是否存在于集合中的方法。其基本原理是使用哈希方法将数据映射到一个很长的向量上。在维基百科上&#xff0c;它被称为“空间效率和查询时间都远远超过一般的算法”的方法。由于它只保存散列的数据&#xff0c;所以对于很长的数据有着良好的压缩特性&a…

递归思想解决输出目录下的全部文件

刚刚了解了下递归思想 递归就是在方法内调用本方法 下面说一个实际的应用 输出目录下的全部文件&#xff0c;当目录中还有目录时&#xff0c;则进入目录输出里面的文件 import java.io.*; class ShowFile{public static void showfile(File files){if(files.isDirectory()){Fi…

实战之网马解密之shellcode篇

今天上卡卡社区发现里面发了个网马解密的链接,呵呵 顺便试试看能解出来不.呵呵. 相信各位已经对网马有点了解了吧.一般网马都是加密了的.关于什么是网马以及怎么防止网马也不是本文的重点.本文是实战shellcode网马解密.以后的博文会放出常见的网马及其解密.以及常见的解密工具的…

机器学习中的线性回归,你理解多少?

作者丨algorithmia编译 | 武明利&#xff0c;责编丨Carol来源 | 大数据与人工智能&#xff08;ID: ai-big-data&#xff09;机器学习中的线性回归是一种来源于经典统计学的有监督学习技术。然而&#xff0c;随着机器学习和深度学习的迅速兴起&#xff0c;因为线性&#xff08;多…

Golang反射机制的实现分析——reflect.Type类型名称

现在越来越多的java、php或者python程序员转向了Golang。其中一个比较重要的原因是&#xff0c;它和C/C一样&#xff0c;可以编译成机器码运行&#xff0c;这保证了执行的效率。在上述解释型语言中&#xff0c;它们都支持了“反射”机制&#xff0c;让程序员可以很方便的构建一…

设计模式----组合模式UML和实现代码

2019独角兽企业重金招聘Python工程师标准>>> 一、什么是组合模式&#xff1f; 组合模式(Composite)定义&#xff1a;将对象组合成树形结构以表示‘部分---整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性. 类型&#xff1a;结构型模式 顺口…

Golang反射机制的实现分析——reflect.Type方法查找和调用

在《Golang反射机制的实现分析——reflect.Type类型名称》一文中&#xff0c;我们分析了Golang获取类型基本信息的流程。本文将基于上述知识和经验&#xff0c;分析方法的查找和调用。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 方法 package mainimpor…

太狠!33岁年薪50万:“复工第一天,谢谢裁掉我!” 网友:有底气!

最近脉脉一则帖子炸锅了&#xff1a;某HR发帖称公司以按时下班为由裁员。这种情况下很多人都慌了&#xff0c;大家纷纷把“副业救国”奉为神律。可是你有没有认真的想过&#xff0c;为什么现在大家都需要副业&#xff1a;意外裁员后&#xff0c;房贷能够按时还上不至于“回收”…

SEO内部链接优化的技巧

内部链接是搜索引擎优化中的重要因素之一。思亿欧做的SEO调查发现&#xff0c;国内大部分网站都没有怎么做内部链接优化。这可能是网站管理员并不知晓SEO或者是对内部链接优化不够重视。 内部链接的设计不能是单纯的为了SEO的目的而作内部链接&#xff0c;同时要注意规划一个良…

Ubuntu 15.10安装ns2.35+nam

2019独角兽企业重金招聘Python工程师标准>>> Step1: 更新系统sudo apt-get update #更新源列表sudo apt-get upgrade #更新已经安装的包sudo apt-get dist-upgrade #更新软件&#xff0c;升级系统Step2:安装ns2需要的几个包sudo apt-get install build-essentialsu…

bug诞生记——不定长参数隐藏的类型问题

这个bug的诞生源于项目中使用了一个开源C库。由于对该C库API不熟悉&#xff0c;一个不起眼的错误调用&#xff0c;导致一系列诡异的问题。最终经过调试&#xff0c;我们发现发生了内存覆盖问题。为了直达问题根节&#xff0c;我将问题代码简化如下&#xff08;转载请指明出于br…

yahoo註冊.com 域名1.99$/年

yahoo註冊.com 域名1.99$/年趕快去註冊吧http://order.sbs.yahoo.com/ds/reviewplanoption?.pYD1&mdom&.srcsbs&.promoBESTDEAL&dzzhen an.com支持paypal付款一個yahoo帳戶只能註冊一個如果覺得續費比較貴&#xff0c;可在註冊兩個月後轉出到godaddy.转载于:h…

Excel弱爆了!这个工具30分钟完成了我一天的工作量,零基础、文科生也能学!...

在大数据浪潮当中&#xff0c;数据分析是这个时代的不二“掘金技能”。我们每一个人&#xff0c;每天无时无刻都在生产数据&#xff0c;一分钟内&#xff0c;微博上新发的数据量超过10万&#xff0c;b站的视频播放量超过600万......这些庞大的数字&#xff0c;意味着什么&#…

Myeclipse快捷键的使用

存盘 Ctrls(肯定知道) 注释代码 Ctrl/ 取消注释 Ctrl\(Eclipse3已经都合并到Ctrl/了) 代码辅助 Alt/ 快速修复 Ctrl1 代码格式化 CtrlShiftf 整理导入 CtrlShifto 切换窗口 Ctrlf6 <可改为ctrltab方便> ctrlshiftM 导入未引用的包 ctrlw 关闭单个窗口 F3 跳转到类、变量的…

PL/SQL三种集合类型的比较

PL/SQL三种集合类型的比较<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />集合是指在一个程序变量中包含多个值。PL/SQL提供的集合类型如下&#xff1a;Associative Array:TYPE t IS TABLE OF something INDEX BY PLS_INTEGER;N…

夺得WSDM Cup 2020大赛金牌的这份参赛方案,速来get!

近日&#xff0c;在美国休斯敦闭幕的第13届网络搜索与数据挖掘国际会议&#xff08;WSDM 2020&#xff09;上&#xff0c;华为云语音语义创新Lab带领的联合团队&#xff0c;摘得WSDM Cup 2020大赛“论文引用意图识别任务”金牌&#xff08;Gold Medal&#xff09;。WSDM被誉为全…

bug诞生记——信号(signal)处理导致死锁

这个bug源于项目中一个诡异的现象&#xff1a;代码层面没有明显的锁的问题&#xff0c;但是执行时发生了死锁一样的表现。我把业务逻辑简化为&#xff1a;父进程一直维持一个子进程。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 首先我们定义一个结构体Pro…

Linux下SVN服务器支持Apache的http和svnserve独立服务器

2019独角兽企业重金招聘Python工程师标准>>> 说明 服务器操作系统&#xff1a;CentOS 6.6 关闭防火墙&#xff0c;SElinux 实现 1、在服务器上安装配置SVN服务&#xff1b; 2、SVN服务支持svnserve独立服务模式访问&#xff1b; 3、SVN服务支持Apache的http模式访问…

AWS攻略——使用CodeCommit托管代码

除了我们熟悉的github&#xff0c;各大云厂商也有自己的代码托管服务。本文讲解如何在Amazon的CodeCommit中托管代码。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 根账户登录 AWS有两种账户登录界面。 IAM账户登录界面 根账户登录界面我们先使用根…

使用alterMIME实现添加message footer功能

1. 安装alterMIME tar zxvf altermime-0.3.8.tar.gz cd altermin3-0.3.8 make make install altermine将被编译安装到/usr/local/bin/2. 使用必备条件&#xff1a;一个运行且配置正常的邮件服务器3. 配置AlterMIME3.1 为altermine创建一个系统帐号&#xff0c;如下&#x…

Facebook最新研究:无需额外训练AI,即可加速NLP任务

作者 | KYLE WIGGERS译者 | Kolen出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;自然语言模型通常要解决两个难题&#xff1a;将句子前缀映射到固定大小的表示形式&#xff0c;并使用这些表示形式来预测文本中的下一个单词。在最近的一篇论文&#xff08;https://ar…

PgSQL · 特性分析 · full page write 机制

PG默认每个page的大小为8K&#xff0c;PG数据页写入是以page为单位&#xff0c;但是在断电等情况下&#xff0c;操作系统往往不能保证单个page原子地写入磁盘&#xff0c;这样就极有可能导致部分数据块只写到4K(操作系统是一般以4K为单位)&#xff0c;这些“部分写”的页面包含…

局域网DVD yum源的制作

今天在网上溜达,看到这篇文章不错,于是就转载过来,感谢原作者的辛苦劳动.源地址:http://blog.chinaunix.net/u3/94782/showart_1953260.html一&#xff1a;两台计算机做实验<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />1&…

AWS攻略——使用S3托管静态网页

在AWS上有很多部署静态网页的方式&#xff0c;比如使用EC2或者Lightsail。但是不管使用上述哪种方案&#xff0c;都需要预先部署如Nignx或者Apache等Http服务。这对纯前端同学来说可能有点复杂&#xff0c;而AWS提供了更简单的部署方式——只需要提供静态网页文件的“S3网页托管…

2020年涨薪26-30%,能实现吗?18%数据科学家是这么期待的

作者丨Big Cloud编译 | 武明利&#xff0c;责编丨Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;本报告将深入探讨亚太地区各个背景、不同年龄和不同地点的专业人员对2019/2020年的见解。今年贡献最大的地区来自新加坡和澳大利亚。因为这些是我们最大的数据点&…