当前位置: 首页> 游戏> 攻略 > 设计制作生态缸_中企动力员工邮箱忘记密码_网游推广员_seo数据分析

设计制作生态缸_中企动力员工邮箱忘记密码_网游推广员_seo数据分析

时间:2025/7/30 20:42:25来源:https://blog.csdn.net/qq_43466788/article/details/144759771 浏览次数:0次
设计制作生态缸_中企动力员工邮箱忘记密码_网游推广员_seo数据分析

文章目录

  • 中间件详解
  • 中间件执行
    • 全局中间件
    • 路由级中间件
    • 运行流程
      • 中间件的链式执行
      • 中断流程
    • 代码示例
  • gin框架总结


中间件详解

Gin 框架中间件是其核心特性之一,主要用于对 HTTP 请求的处理进行前置后置的逻辑插入,例如日志记录、身份认证、错误处理等。

我们在创建默认的gin引擎时:r := gin.Default()

func Default() *Engine {debugPrintWARNINGDefault()engine := New()engine.Use(Logger(), Recovery())  // 默认注册的两个中间件return engine
}

通过Use()函数注册了Logger中间件和Recovery中间件,Use()函数:

// 也就是说,通过 Use() 连接的中间件将被
// 包含在每个请求的处理程序链中。即使是 404、405、静态文件...
// 例如,这里适合放置日志记录器或错误管理中间件。
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {engine.RouterGroup.Use(middleware...)engine.rebuild404Handlers()engine.rebuild405Handlers()return engine
}

实际上还是调用的RouterGroup的Use函数:

// 使用将中间件添加到组中。
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {group.Handlers = append(group.Handlers, middleware...)return group.returnObj()
}

注册中间件其实就是将中间件函数追加到group.Handlers中。

type RouterGroup struct {Handlers HandlersChainbasePath stringengine   *Engineroot     bool
}type HandlersChain []HandlerFunc// HandlerFunc 定义了 gin 中间件作为返回值使用的处理程序。
type HandlerFunc func(*Context)

跟踪这个结构找到HandlersChain ,这是 Gin 中保存中间件和处理函数的核心数据结构,中间件和最终处理函数都以 HandlerFunc 的形式存储在链中。

Context 是 Gin 中非常重要的对象,负责在中间件之间传递数据:

type Context struct {Request        *http.Request    // 当前的 HTTP 请求Writer         http.ResponseWriter // 响应输出handlers       HandlersChain    // 当前请求的中间件链index          int8             // 当前执行到的中间件索引Keys           map[string]any   // 自定义上下文数据存储// 其他字段...
}

核心字段

  • handlers: 保存当前路由的中间件链。
  • index: 标记当前执行到第几个中间件。
  • Keys: 用于存储自定义的上下文数据,在中间件之间共享。

注册路由时,会将对应路由的函数和之前的中间件函数结合到一起:
handlers = group.combineHandlers(handlers) // 将处理请求的函数与中间件函数结合


中间件执行

Gin 中间件分为全局中间件和路由级中间件两种,最终都保存在 HandlersChain 中。

全局中间件

全局中间件通过 Engine.Use() 方法注册,作用于所有路由。

  1. 调用 Use() 方法,将中间件追加到 Engine 的默认 handlers 中。
  2. 在每次请求处理时,默认中间件会首先执行。
func (group *RouterGroup) Use(middleware ...HandlerFunc) *RouterGroup {group.Handlers = append(group.Handlers, middleware...) // 注册中间件return group
}r := gin.Default() // gin.Default() 内置了 Logger 和 Recovery 全局中间件

路由级中间件

路由级中间件通过在特定路由上链式调用 Use() 方法注册。

  1. 路由级中间件注册时,保存在当前路由的 HandlersChain 中。
  2. 在匹配到具体路由时,这些中间件会被加入到 Contexthandlers 中,并按顺序执行。
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {handlers = group.combineHandlers(handlers) // 合并路由级中间件和处理函数group.engine.addRoute("GET", path, handlers)return group.returnObj()
}

运行流程

中间件的链式执行

Gin 使用 Context 中的 index 字段来控制中间件的链式调用:

  • index 表示当前执行到的中间件索引。
  • 每个中间件需要调用 c.Next() 才能执行下一个中间件。
  • 如果某个中间件不调用 c.Next(),后续的中间件和处理函数将不会执行(终止流程)。
func (c *Context) Next() {c.index++for c.index < int8(len(c.handlers)) {c.handlers[c.index](c) // 执行下一个中间件或处理函数c.index++}
}

通过索引遍历HandlersChain链条,从而实现依次调用该路由的每一个函数(中间件或处理请求的函数)。

以一个请求路径为例,假设 /hello 路径注册了两个中间件和一个处理函数:

r.GET("/hello", middleware1, middleware2, finalHandler)

执行顺序如下:

  1. 进入 middleware1
  • 如果调用 c.Next(),继续执行下一个中间件。
  1. 进入 middleware2
  • 如果调用 c.Next(),执行 finalHandler
  1. 返回时按链路逆序执行剩余代码。

中断流程

某个中间件不调用 c.Next()

func middleware1(c *gin.Context) {c.JSON(401, gin.H{"error": "unauthorized"})c.Abort() // 停止后续中间件执行
}
  • 调用 c.Abort() 会终止后续中间件或处理函数的执行。
  • 标志位 c.index 被设置为最大值。

代码示例

  1. 全局中间件
package mainimport ("github.com/gin-gonic/gin"
)func Logger() gin.HandlerFunc {return func(c *gin.Context) {// 执行前fmt.Println("Logger - Before Request")c.Next() // 执行下一个中间件// 执行后fmt.Println("Logger - After Request")}
}func main() {r := gin.New()// 注册全局中间件r.Use(Logger())r.GET("/hello", func(c *gin.Context) {c.String(200, "Hello World")})r.Run(":8080")
}

执行流程:

Logger - Before Request
Hello World
Logger - After Request
  1. 路由级中间件
package mainimport ("github.com/gin-gonic/gin"
)func Middleware1() gin.HandlerFunc {return func(c *gin.Context) {fmt.Println("Middleware1 - Before")c.Next()fmt.Println("Middleware1 - After")}
}func Middleware2() gin.HandlerFunc {return func(c *gin.Context) {fmt.Println("Middleware2 - Before")c.Next()fmt.Println("Middleware2 - After")}
}func main() {r := gin.New()r.GET("/test", Middleware1(), Middleware2(), func(c *gin.Context) {fmt.Println("Final Handler")c.String(200, "OK")})r.Run(":8080")
}

执行流程:

Middleware1 - Before
Middleware2 - Before
Final Handler
Middleware2 - After
Middleware1 - After
  1. 流程中断
func AuthMiddleware() gin.HandlerFunc {return func(c *gin.Context) {token := c.GetHeader("Authorization")if token == "" {c.JSON(401, gin.H{"error": "unauthorized"})c.Abort() // 中断流程return}c.Next()}
}r.GET("/secure", AuthMiddleware(), func(c *gin.Context) {c.String(200, "Secure Data")
})

gin框架总结

Engine 是 Gin 框架的核心数据结构,负责路由注册、HTTP 请求处理,以及中间件的全局管理。

type Engine struct {RouterGroup            // 继承了 RouterGroup,用于路由分组和中间件管理handlers     HandlersChain // 全局中间件链methodTrees  methodTrees   // 路由树存储,不同 HTTP 方法对应一棵 Radix 树ContextPool  sync.Pool     // 上下文对象池,复用 Context 提高性能
}
  1. RouterGroup:
    • 用于路由分组。
    • 支持分组级别的中间件注册。
  2. methodTrees:
    • 保存路由信息的核心,methodTrees 是一组 Radix 树,不同 HTTP 方法(如 GET、POST)对应一棵独立的路由树。
    • 每个树节点存储路由路径的部分信息,并链接到处理函数。
  3. handlers:
    • 全局中间件链,所有路由共享的中间件。
  4. ContextPool:
    • 通过对象池复用 Context,减少内存分配和垃圾回收的开销。

路由树构建:methodTrees 是路由信息存储的核心结构,不同 HTTP 方法各自维护一棵 Radix 树。

type methodTrees []methodTreetype methodTree struct {method string // HTTP 方法,如 GET、POSTroot   *node  // Radix 树的根节点
}
  • Gin 在注册路由时,使用路径分段递归构建 Radix 树。

  • 每个路由的处理函数和中间件保存在树节点的 handlers 字段中。

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {// 找到对应的 Radix 树root := engine.methodTrees.get(method).rootroot.addRoute(path, handlers)
}

RouterGroup 用于路由的分组和中间件管理,通过分组可以为一组路由统一添加中间件或前缀。

type RouterGroup struct {Handlers HandlersChain // 路由分组级中间件basePath string        // 分组路径前缀engine   *Engine       // 指向顶层的 Engine
}
  • 分组路由:通过 Group() 方法创建子分组,支持嵌套分组。
  • 注册中间件:分组级中间件通过 Use() 方法注册,作用范围为该分组及其子分组。

HandlersChain 是一个中间件链表,保存所有的中间件和处理函数,按顺序执行。

type HandlersChain []HandlerFunctype HandlerFunc func(*Context)
  • 接收 *Context 参数,在 HTTP 请求的生命周期中共享数据。

  • 可通过调用 c.Next() 继续执行下一个中间件。

Context 是 Gin 中最重要的组件之一,用于在中间件和处理函数之间传递数据。

type Context struct {Request        *http.Request    // 当前请求Writer         http.ResponseWriter // 当前响应handlers       HandlersChain    // 当前中间件链index          int8             // 当前中间件执行位置Keys           map[string]any   // 用于存储用户自定义数据// 其他字段...
}

中间件链控制

  • 调用 c.Next() 执行下一个中间件。
  • 调用 c.Abort() 中断执行链。

响应输出

  • 通过 c.JSON()c.String() 等方法生成 HTTP 响应。

自定义数据存储

  • c.Set()c.Get() 用于在中间件间共享数据。

Gin 的中间件机制非常灵活,支持全局、分组、路由级中间件。

  • 中间件链以 HandlersChain 的形式保存。
  • 链式调用,每个中间件通过 c.Next() 调用下一个中间件。

总的流程:

  1. 路由匹配
  • 根据 HTTP 方法,从 methodTrees 中选择对应的 Radix 树。
  • 使用路径递归查找匹配的节点。
  1. 中间件执行
  • 匹配成功后,合并全局中间件、分组中间件和路由级中间件,形成完整的 HandlersChain
  • 按链式顺序调用中间件。
  1. 处理函数执行
  • 执行完所有中间件后,最终调用路由处理函数。
  1. 返回响应
  • 通过 Context 的方法生成 HTTP 响应。

关键字:设计制作生态缸_中企动力员工邮箱忘记密码_网游推广员_seo数据分析

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: