ErrorMiddleware在gin中间件放前还是后
📅 2026/7/30 12:44:09
👁️ 阅读次数
📝 编程学习
放最前面(越早注册越好)。
go
r := gin.New() // ✅ 正确:ErrorMiddleware 第一个注册 r.Use(ErrorMiddleware()) // 其他中间件 r.Use(LoggerMiddleware()) r.Use(AuthMiddleware()) r.Use(CORSMiddleware()) // 路由 r.GET("/api/user", getUser)为什么必须放前面?
Gin 中间件是洋葱模型,注册顺序决定嵌套层次:
plain
ErrorMiddleware (最外层) └── LoggerMiddleware └── AuthMiddleware └── Handler (最内层)1. recover 必须在最外层
defer recover()只能捕获同一线程(goroutine)内的 panic。如果ErrorMiddleware放在后面:
go
r.Use(AuthMiddleware()) // 如果这里 panic,ErrorMiddleware 捕获不到! r.Use(ErrorMiddleware()) // ❌ 太晚了只有放在最前面,它的defer才能包裹住后续所有中间件和 Handler。
2. c.Errors 检查不受顺序影响(但放前面更统一)
因为c.Errors是在c.Next()之后检查,无论放哪都能拿到前面累积的错误。但通常规范是:
错误恢复/统一响应 → 最前面
日志记录 → 放 ErrorMiddleware 后面(让它先恢复,再记录)
鉴权/限流 → 更后面
常见正确顺序
go
r.Use(ErrorMiddleware()) // 1. 恢复 + 统一错误响应 r.Use(LoggerMiddleware()) // 2. 记录请求日志(包括错误状态) r.Use(AuthMiddleware()) // 3. 鉴权 r.Use(RateLimit()) // 4. 限流⚠️ 注意:不要和 gin.Recovery() 一起用
如果你已经用了gin.Default()(内置 Recovery),不要再套自己的 recover,否则内置的先捕获,你的ErrorMiddleware永远 recover 不到:
go
// ❌ 错误:gin.Default 已经内置 Recovery r := gin.Default() r.Use(ErrorMiddleware()) // 这里的 recover 永远抓不到 panic // ✅ 正确:用 gin.New() + 你自己的 ErrorMiddleware r := gin.New() r.Use(ErrorMiddleware())一句话总结:recover 中间件就像 try-catch,必须包在最外层。
编程学习
技术分享
实战经验