iris 不支持用 recovery 中间件捕获崩溃异常,因其仅对中间件链内部 panic 有效,而路由或 mvc 方法中的 panic 已被底层提前捕获并返回 500;应主动返回结构化错误(如 *apperror)并由中间件统一处理。

别用 Recovery 中间件捕获崩溃异常 —— Iris 明确不支持、也不推荐这么做。
为什么 Recovery 中间件在 Iris 中基本无效
Iris 的 recovery.Recovery 中间件(来自第三方 github.com/kataras/iris/v12/middleware/recovery)仅对它所在中间件链**内部**发生的 panic 有效;一旦 panic 发生在后续 handler(比如你的路由函数或 MVC 方法里),Iris 底层的 http.Handler 封装层已提前捕获并记录日志,同时返回 500 响应,此时 recovery.Recovery 根本收不到 panic。
- 它无法拦截 MVC 控制器方法里的 panic(Iris 内部已处理)
- 它不能覆盖
app.OnErrorCode(500, ...)的行为,后者只响应未匹配路由或未 recover 的顶层 panic - 即使启用,你也拿不到原始错误上下文(比如数据库连接中断 vs 参数空指针),因为 panic 已被转为通用 500
真正该拦截的不是 panic,而是业务 error
Iris 的设计哲学是:**把错误当值传,而不是当异常抛**。所有 handler 应主动返回结构化错误(如 *AppError),由中间件统一识别和响应。
- 定义标准错误类型:
type AppError struct { Code int; Message string; Err error } - 在 handler 中显式判断并响应:
if err := db.Query(...); err != nil { return ctx.JSON(500, &AppError{Code: 500, Message: "DB query failed"}) } - 注册兜底中间件,只处理未被 handler 主动响应的 error:
ctx.Response().StatusCode() == 0才写默认 500
如果非要处理 panic,必须手动且精准
仅在极少数场景(如插件调用不可信第三方库)需要 recover,且必须满足:
- 在自定义中间件里写
defer func() { if r := recover(); r != nil { ... } }() - recover 后必须做类型断言:
if be, ok := r.(*BizError); ok { ctx.StatusCode(be.Code) },否则一律转 500 - 绝对不要在 MVC Controller 方法里依赖
return err—— Iris MVC 完全忽略返回值中的 error - panic 前确保没有并发访问
ctx(iris.Context不可跨 goroutine 使用)
最常被忽略的一点:Iris 的 panic 处理是「日志 + 500 响应」两步原子操作,你加的任何 recover 都无法改变这个默认行为,只能在它之前做更细粒度的分类响应 —— 所以重点永远该放在“怎么让错误早暴露、早结构化”,而不是“怎么兜住 panic”。











