Gin中间件链执行机制
中间件链是Gin框架的核心特性,采用洋葱模型实现请求的分层处理。
中间件链结构
Go
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
type Context struct {
handlers HandlersChain // 中间件链
index int8 // 当前执行索引
// ...
}
const abortIndex int8 = 63 // 最大索引,用于中断
执行流程原理
Next方法实现
Go
func (c *Context) Next() {
c.index++
for c.index < int8(len(c.handlers)) {
c.handlers[c.index](c)
c.index++
}
}
Abort方法实现
Go
func (c *Context) Abort() {
c.index = abortIndex
}
func (c *Context) AbortWithStatus(code int) {
c.Status(code)
c.Abort()
}
洋葱模型执行顺序
Go
请求 → Middleware1前 → Middleware2前 → Handler → Middleware2后 → Middleware1后 → 响应
←──────────────────────────────────────────────────────────────
执行过程示例
Go
func Middleware1() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("Middleware1 前置处理")
c.Next()
fmt.Println("Middleware1 后置处理")
}
}
func Middleware2() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("Middleware2 前置处理")
c.Next()
fmt.Println("Middleware2 后置处理")
}
}
// 输出顺序:
// Middleware1 前置处理
// Middleware2 前置处理
// Handler 处理
// Middleware2 后置处理
// Middleware1 后置处理
中间件注册方式
全局中间件
Go
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(CORSMiddleware())
路由组中间件
Go
api := r.Group("/api")
api.Use(AuthMiddleware())
{
api.GET("/users", getUsers)
api.POST("/users", createUser)
}
单路由中间件
Go
r.GET("/protected", AuthMiddleware(), handler)
中间件链合并
Go
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)
copy(mergedHandlers, group.Handlers)
copy(mergedHandlers[len(group.Handlers):], handlers)
return mergedHandlers
}
执行索引追踪
| 阶段 | index值 | 执行内容 |
|---|---|---|
| 初始 | -1 | 等待执行 |
| Middleware1前置 | 0 | 执行handlers[0] |
| Middleware2前置 | 1 | 执行handlers[1] |
| Handler | 2 | 执行handlers[2] |
| Middleware2后置 | 2 | 从Next返回 |
| Middleware1后置 | 1 | 从Next返回 |
Abort中断机制
Go
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"})
return // 必须return,Abort只设置index
}
c.Next()
}
}
func handler(c *gin.Context) {
// 认证失败时不会执行
c.JSON(200, gin.H{"message": "success"})
}
// 执行流程:
// 1. AuthMiddleware检查token
// 2. token为空时Abort设置index=63
// 3. return退出中间件
// 4. Next循环检测index>=len(handlers),结束执行
注意:调用Abort后必须显式return,否则会继续执行当前函数剩余代码。
检查是否已中断
text
func (c *Context) IsAborted() bool {
return c.index >= abortIndex
}
// 使用示例
func SomeMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if c.IsAborted() {
return // 后续逻辑不执行
}
// 正常情况的后置处理
log.Println("Request completed successfully")
}
}
要点总结
- handlers链存储所有中间件和处理函数
- index跟踪当前执行位置,初始为-1
- Next()递增index并执行下一个handler
- Abort()设置index=63中断链执行
- 洋葱模型:前置代码在Next前,后置在Next后
- Abort后必须return退出当前函数
📝 发现内容有误?点击此处直接编辑