参考资料

  1. https://study.163.com/course/courseMain.htm?courseId=1210171207 李文周Mooc
  2. https://www.liwenzhou.com/posts/Go/read_gin_sourcecode/#autoid-0-1-3 李文周博客

使用中间件程序示例

  1. func main() {
  2. r := gin.Default()
  3. r.Use(func(context *gin.Context) {
  4. fmt.Printf("this is a middleware\n")
  5. })
  6. r.GET("/", func(c *gin.Context) {
  7. ......
  8. }

中间件注册

Engine.Use

  1. // 404,405也注册了中间件
  2. func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
  3. engine.RouterGroup.Use(middleware...)
  4. engine.rebuild404Handlers()
  5. engine.rebuild405Handlers()
  6. return engine
  7. }

RouterGroup.Use

  1. func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
  2. // 直接在对应的路由组的Hanlers中添加对应方法
  3. group.Handlers = append(group.Handlers, middleware...)
  4. return group.returnObj()
  5. }

中间件的执行

路由匹配中执行以下代码

  1. root := t[i].root
  2. // Find route in tree
  3. value := root.getValue(rPath, c.params, unescape)
  4. if value.params != nil {
  5. c.Params = *value.params
  6. }
  7. if value.handlers != nil {
  8. c.handlers = value.handlers
  9. c.fullPath = value.fullPath
  10. c.Next()
  11. c.writermem.WriteHeaderNow()
  12. return
  13. }

其中c.Next()

  1. func (c *Context) Next() {
  2. c.index++
  3. // 顺序执行Hanlers中的函数
  4. for c.index < int8(len(c.handlers)) {
  5. c.handlers[c.index](c)
  6. c.index++
  7. }
  8. }

中间件注册方式

  1. func main() {
  2. // Default自带logger和recover中间件
  3. r := gin.Default()
  4. // 为根路径注册中间件(在所有处理函数之前调用)
  5. r.Use(func(context *gin.Context) {
  6. fmt.Printf("this is a middleware\n")
  7. })
  8. // 两种方式为路由组注册中间件
  9. shopGrout := r.Group("/shop", func1)
  10. shopGrout.Use(func2)
  11. ...
  12. ...
  13. }

调用链的管理: c.Next(), c.Abort()

  • 在某个处理方法中间调用c.Next()可以使之后的处理函数先执行,再执行该方法的剩余部分
  • 在某个处理方法的中间使用c.Abort(),index值将被置为最大,后面的处理函数将不再执行