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服务中,我们应该首先 ...
随机推荐
- Python 第五阶段 学习记录之---Django 进阶
Model 一.创建表 1.基本结构 字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...
- mysql 终止 存储过程
[1]如下图所示 有时候,存储过程执行语句中有循环,且已启动.但出于某种原因,我们突然不想让其再继续执行,需要终止其线程. Good Good Study, Day Day UP. 顺序 选择 循环 ...
- Windwos Live Writer插件指南
Windows Live Writer 即(WLW) 是一个免费的桌面应用程序,可以用于发布博客. 官网下载地址:https://www.microsoft.com/zh-CN/download/de ...
- pypi上传命令
windows 1.新建一个setup.py文件与你自己写的.py模块放在一个文件夹内 内容: from distutils.core import setup setup( name = " ...
- SSM-网站后台管理系统制作(2)---SSM基本工作原理
SSM基本工作原理 讲解网站:https://www.w3cschool.cn/wkspring/dcu91icn.html 构建基本工作环境: mysql eclipse(tomcat8.0) Hb ...
- JDK的安装与测试
一,下载并安装JDK1.8版本以上 1.Oracle官网下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downl ...
- ckeditor5 增加居中alignment
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html 克隆下来 gi ...
- 算法笔记--极大极小搜索及alpha-beta剪枝
参考1:https://www.zhihu.com/question/27221568 参考2:https://blog.csdn.net/hzk_cpp/article/details/792757 ...
- webpack点滴
一个比较完整的webpack的配置,自己配置不断更新. const path = require('path') const configs = require('./configs/') const ...
- ionic3 双向数据绑定失效 脏值检测失效
最近在使用ionic3过程中,使用了eval()方法进行字符串拼接成一个function使用 在eval()方法中,只能使用局部变量,全局变量无法使用,ionic3的this在eval中失效(unde ...