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服务中,我们应该首先 ...
随机推荐
- U盘安装Windows Server 2008 r2失败,改用磁盘安装
一.使用UltraISO制作系统安装启动U盘提示错误“缺少所需的CD/DVD驱动器设备驱动程序.…………”试了各种方法都不能通过U盘进行安装. 二.直接使用磁盘安装0.使用PE先将磁盘格式化.分区.1 ...
- 小程序canvas生成海报保存至手机相册
小程序canvas画图保存至手机相册 (1)可直接展示生成的海报 .因手机分辨率不同可能导致生成的海报会有细微差别,这里隐藏canvas海报,页面正常设置海报样式保存时保存隐藏的canvas海报 (2 ...
- hashlib、hmac
#hashlib import hashlib#md5m = hashlib.md5()m.update(b"Hello")print(m.hexdigest()) #hexdig ...
- 软件安全概念:认证 & 授权
认证 证明你是谁,这个过程就是认证 授权 你能干什么
- JavaScript中的变量提升和函数提升
在EcmaScript5中只有全局作用域和函数作用域,EcmaScript6增加了块级作用域. 块级作用域(一对花括号{}即为一个块级作用域) 变量提升 console.log(name); //un ...
- Dockerfile构建容器---语法高亮
三个文件扔进相关的目录即可 wget -O /usr/share/vim/vimfiles/doc/dockerfile.txt https://raw.githubusercontent.com/a ...
- 对负载均衡的理解及nginx负载均衡的配置
https://blog.csdn.net/qq_28602957/article/details/61615876
- 实体关系图应用——google ads
实体关系 本页展示了 AdWords 实体的关系图,其中的可点击图片可帮助您找到最合适的文档. 表示法图例 实体:链接到相关性最高的指南. 基数:允许的实例数量.例如,1..\* 表示允许一个或多个. ...
- Learning-MySQL【3】:数据类型和运算符
一.数据类型 1.数值类型 为每张表的每个字段选择合适的数据类型是数据库设计过程中一个重要的步骤. 数字分为整数和小数.其中整数用整数类型表示,小数用浮点数类型和定点数类型表示. 浮点数类型包括单精度 ...
- ajax全选、全不选、反选、单删/批删
<meta charset="utf-8"> <?php //链接数据库 $link = mysqli_connect('127.0.0.1','root','r ...