go web framework gin middleware 设计原理
场景:一个middleware可以具体为一个函数,而由前面的gin 路由分析可得,每一个路径都对有一个HandlersChain 与其对应。
那么实际上增加一个middleware的过程,就是将每一个路由策略加进来之前,与其绑定,这样就能使得这一类的路由到来的时候触发这个中间件生效。
下面看看gin web framework中是如何实现的?
首先是:gin.default()函数
// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery()) #加载Logger(), 和Recovery()中间件
return engine
}
然后查看engine.Use()
// Use attachs a global middleware to the router. ie. the middleware attached though Use() will be
// included in the handlers chain for every single request. Even 404, 405, static files...
// For example, this is the right place for a logger or error management middleware.
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
engine.RouterGroup.Use(middleware...) #这个函数的参数是一个不定参数,也就是说我们可以追加的中间件没有限制
engine.rebuild404Handlers()
engine.rebuild405Handlers()
return engine
}
接着是engine.RouterGroup.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...) #将middleware暂存在group.Handlers中
return group.returnObj()
}
这个时候,我们再来看一个路由信息的调用过程,如,我们定义一个Get的路由
// Ping test
r.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
查看r.GET函数的实现
// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("GET", relativePath, handlers) #将handlers 函数以及相对路径传递给group.handle()函数
}
查看group.handle()函数的实现
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
absolutePath := group.calculateAbsolutePath(relativePath) #计算绝对路径
handlers = group.combineHandlers(handlers) #将参数的handlers 和 middleware 的handlers拼接在一起作为一条路由信息,传递给addRoute()函数
group.engine.addRoute(httpMethod, absolutePath, handlers)
return group.returnObj()
}
查看group.combineHandlers()函数的实现
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) #创建一个HandlersChain的数组,然后把group.handlers 和 参数的handlers copy 进去
copy(mergedHandlers, group.Handlers)
copy(mergedHandlers[len(group.Handlers):], handlers)
return mergedHandlers
}
于是每一条路由的达到,如果根据基树找到这里的HandlersChain,那么就会触发该HandlersChain中所有的func, 至于如何找到的,查看gin 启动流程分析这篇文章。
这样的中间件设计有什么优缺点呢?
优点:保证所有的路由信息都会用到中间件。
缺点:如果中间件并不适用于所有的路由策略,则更改起来比较麻烦,需要在中间件内部根据context做判断。
go web framework gin middleware 设计原理的更多相关文章
- go web framework gin 路由表的设计
在上一篇go web framework gin 启动流程分析这一篇文章中,我分析了go gin启动的过程,在这一篇文章中我将继续上面的分析,讨论gin 中路由表是如何设计的? 首先查看engine. ...
- go web framework gin group api 设计
假如让你来设计group api, 你该怎么设计呢? group api 和普通api的区别在于前缀不同,如果group api的版本为v1.0 那么相对应的url为/v1.0/xxx, 如果是普通a ...
- go web framework gin 启动流程分析
最主要的package : gin 最主要的struct: Engine Engine 是整个framework的实例,它包含了muxer, middleware, configuration set ...
- html5设计原理(转)
转自: http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一 ...
- 学习HTML5必读之《HTML5设计原理》
引子:很久前看过的一遍受益匪浅的文章,今天再次转过来,希望对学习HTML5的朋友有所帮助. 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一方面,当然了,就是HTML5.我可以站在这儿只讲HT ...
- 介绍一个python的新的web framework——karloop框架
karloop是一款轻型的web framework,和tornado.webpy类似.mvc分层设计,眼下已经公布早期版本号了,使用方便, 下载地址例如以下:https://github.com/k ...
- BigPipe设计原理
高性能页面加载技术--BigPipe设计原理及Java简单实现 1.技术背景 动态web网站的历史可以追溯到万维网初期,相比于静态网站,动态网站提供了强大的可交互功能.经过几十年的发展,动态网站在互动 ...
- Jena 简介:通过 Jena Semantic Web Framework 在 Jave 应用程序中使用 RDF 模型
简介: RDF 越来越被认为是表示和处理半结构化数据的一种极好选择.本文中,Web 开发人员 Philip McCarthy 向您展示了如何使用 Jena Semantic Web Toolkit,以 ...
- Web Service进阶(一)运行原理
利用清明小假期,温习了一遍Web Service的相关内容,对其工作原理进行了简要总结.以供有需求的朋友和自己日后参考.文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉. Web服务中,我们应该首先 ...
随机推荐
- Delphi中类的运行期TypeInfo信息结构说明(转载)
Delphi中类的运行期TypeInfo信息结构说明作者:刘啸CnPack开发组 http://www.cnpack.org关键字:RTTI, TypeInfo, TypeData, PropInfo ...
- scrapy item pipeline
item pipeline process_item(self, item, spider) #这个是所有pipeline都必须要有的方法在这个方法下再继续编辑具体怎么处理 另可以添加别的方法 ope ...
- 详解Python变量在内存中的存储
这篇文章主要是对python中的数据进行认识,对于很多初学者来讲,其实数据的认识是最重要的,也是最容易出错的.本文结合数据与内存形态讲解python中的数据,内容包括: 引用与对象 可变数据类型与不可 ...
- 软件工程实践小项目之模拟wc.exe的小程序
github源码和工程文件地址:https://github.com/Jackchenyu/Word_counts/tree/smart 基本要求:要实现wc的基本功能即文件中字符数.单词数.行数的统 ...
- KNN算法 - 数据挖掘算法(3)
(2017-04-10 银河统计) KNN算法即K Nearest Neighbor算法.这个算法是机器学习里面一个比较经典的.相对比较容易理解的算法.其中的K表示最接近自己的K个数据样本.KNN算法 ...
- np.meshgrid()用法+ np.stack()用法
A,B,C,D,E,F是6个网格点,坐标如图,如何用矩阵形式(坐标矩阵)来批量描述这些点的坐标呢?答案如下 这就是坐标矩阵——横坐标矩阵X XX中的每个元素,与纵坐标矩阵Y YY中对应位置元素,共同构 ...
- 基于Docker搭建MySQL多源复制环境
MySQL5.7在主从复制上面相对之前版本多了一些新特性,包括多源复制.基于组提交的并行复制.在线修改Replication Filter.GTID增强.半同步复制增强等. 多源复制:多源复制加入了一 ...
- cpu使用率低负载高,原因分析
原因总结 产生的原因一句话总结就是:等待磁盘I/O完成的进程过多,导致进程队列长度过大,但是cpu运行的进程却很少,这样就体现到负载过大了,cpu使用率低. 下面内容是具体的原理分析:在分析负载为什么 ...
- rds下载备份集在另外一台机器上恢复并应用binlog日志
-----------------------------备份还原并启动数据库----------------------------------1.创建目录,并把下载的压缩文件拷贝到相应的目录[ro ...
- 【JS】Js对json的转换
将json字符串转换为json对象的方法.在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键 例如: JSON ...