Gin 中的 next
func main() {
r := gin.Default()
r.Use(func(c *gin.Context) {
fmt.Println(1, " ")
c.Next()
fmt.Println(6, " ")
})
r.Use(func(c *gin.Context) {
fmt.Println(2, " ")
fmt.Println(5, " ")
})
r.Use(func(c *gin.Context) {
fmt.Println(3, " ")
c.Next()
fmt.Println(4, " ")
})
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
r.Run("localhost:8080")
}
// 打印 1 2 5 3 4 6
Gin 中使用 gin.go Use 函数注册中间件
最终调用 routergroup.go Use 函数, 放入 group.Handlers 队列中
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
engine.RouterGroup.Use(middleware...)
engine.rebuild404Handlers()
engine.rebuild405Handlers()
return engine
}
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
group.Handlers = append(group.Handlers, middleware...)
return group.returnObj()
}
func (c *Context) Next() {
c.index++
for c.index < int8(len(c.handlers)) {
c.handlers[c.index](c)
c.index++
}
}
在 Next 函数中可以看到, 通过控制 index 来控制中间件的结束
并且默认在执行完上一个中间件之后, 即使不调用 Next 也会继续调用下一个中间件
const abortIndex int8 = math.MaxInt8 >> 1
func (c *Context) Abort() {
c.index = abortIndex
}
在注册中间件时, 有个数量判断, 数量必须小于 abortIndex
所以在 Gin 里中断剩余中间件的方法 Abort 函数的实现是对 index 赋值
总结
- 中间件代码无论是否有调用 Next() 方法,后续中间件也会执行
- 中间件调用 Next() 方法之后, 会先执行后面的中间件最后再执行当前中间件的剩余代码
- 中断剩余中间件需要使用 Abort() 方法, 但当前中间件的剩余代码以及调用了 Next() 的中间件的剩余代码还会继续执行