gin的Next()方法使用
源代码/数据集已上传到 Github - posts
使用gin这个web框架开发http服务,少不了使用中间件。
在调用gin.Default()方法的时候就会自动使用Logger
和Recovery()
两个中间件。
仔细查看两个中间件的实现,你会发现,两个中间件都有c.Next()
这个方法的调用。
很多人把Next放在中间的最后一行,然后发现加不加next似乎并没有什么区别。所以,它到底是怎么用的?
来自SF的引用文章:goalng框架Gin中间件的c.Next()有什么作用?
上图可以说是Next()方法的一个形象化的解释
不使用 Next()
假设我们去编写这样的一段代码
1 | route := gin.Default() |
而middleware.RequestID
的实现如下
1 | func RequestID(ctx *gin.Context) { |
middleware.Log
的实现如下
1 | func Log(ctx *gin.Context) { |
app.Index
的实现如下
1 | func Index(ctx *gin.Context) { |
请求后可以在日志中信息中获取到
1 | 2020/02/09 23:53:45 request start |
日志显示,程序按照代码中定义的顺序request
=> log
=> index
执行了。
使用 Next()
那加入了Next()
后怎么执行呢
如下为两个中间加入后的实际代码
1 | func RequestID(ctx *gin.Context) { |
1 | func Log(ctx *gin.Context) { |
请求后,从日志中可以得知如下信息
1 | 2020/02/09 23:58:45 request start |
程序先执行到 request start
,遇到Next
,就去执行log start
,又遇到Next
。去执行app.Index
,返回执行log end
,再是request end
。
出现了一种先进后出的情况。而这个就是上面图片上画的洋葱模型。
分析Next()的实现
Next()
方法的实现非常简单
1 | route.Use(middleware.RequestID) |
代码入口加载中间件就是往c.handlers
中append这个方法。
1 | func (c *Context) Next() { |
而每一次调用Next
都会调用当前index的下一个索引位的方法,开始自增循环,直到index已经比所有的中间件数量还要大了,就会开始执行业务代码。当业务代码执行完后,就会一层一层的往外执行每个中间件未执行完的代码。
洋葱模式在实际业务中如何使用?
- 计算业务程序实际耗时
我们来写一个ExecTime
的中间件
1 | func ExecTime(ctx *gin.Context) { |
放在离路由开始最近的位置
1 | route := gin.Default() |
请求后,从日志中可以得知如下信息
1 | 2020/02/10 00:06:51 request start |
执行耗时在业务代码执行完后就输出了
- 程序异常的捕捉和报警
- 链路跟踪
微信扫一扫,阅读/分享
edit this page last updated at 2024-04-22