iris错误处理需显式调用ctx.statuscode()才能触发onerrorcode注册函数,它不是全局异常监听而是状态码响应钩子;404须通过兜底路由主动设码,500类panic需recovery中间件捕获。

iris 的错误处理不是靠 panic 捕获或中间件兜底,而是分层注册 + 状态码触发 —— 你必须显式调用 ctx.StatusCode() 才能激活对应 OnErrorCode 处理函数。
OnErrorCode 注册后不会自动生效
很多人误以为注册了 app.OnErrorCode(iris.StatusNotFound, handler) 就能捕获所有 404,结果发现访问不存在路由时压根没进 handler。这是因为:OnErrorCode 只是注册一个“备用处理器”,它不会拦截请求,也不会修改默认行为。
- 默认 404 响应由 iris 内置的未匹配路由逻辑生成,不经过任何
OnErrorCode回调 - 只有当 handler 显式调用
ctx.StatusCode(404)(或等价常量如iris.StatusNotFound)时,框架才查表并执行对应注册函数 - 换句话说:这不是“全局异常监听”,而是“状态码响应钩子”
404 场景下如何真正启用自定义处理
想让 404 走自定义逻辑,必须主动制造一次 404 响应。常见做法是在最后加一个兜底路由:
app.Get("/{any:path}", func(ctx iris.Context) {
ctx.StatusCode(iris.StatusNotFound)
// 此时才会触发 OnErrorCode(iris.StatusNotFound, ...)
})
- 这个兜底路由必须放在所有其他
Get/Post之后,否则会提前截断正常请求 - 不能依赖
app.NotFound(...),那个只影响未匹配路径的最终响应体,不触发OnErrorCode - 如果用了子路由器(
Party),需在对应Party上单独注册OnErrorCode,它不继承父级
StatusCode 和错误传递的耦合陷阱
OnErrorCode handler 接收的 iris.Context 是原始请求上下文,但它的 Values()、Params() 等数据来自触发 StatusCode 的那个 handler,不是原始路由 handler。
- 比如你在
/user/{id}中校验 id 不存在,调用ctx.StatusCode(404),此时OnErrorCodehandler 能拿到id参数值 - 但如果你在中间件里统一判断并设 404,
OnErrorCodehandler 就拿不到路由参数,因为中间件执行时参数尚未解析完成 -
ctx.Values().Set()是跨 handler 传参的唯一可靠方式,但要注意生命周期 —— 它只活到当前请求结束
500 类错误不能仅靠 OnErrorCode 捕获
OnErrorCode(iris.StatusInternalServerError, ...) 只对显式调用 ctx.StatusCode(500) 有效,对 panic、空指针、数据库超时等未被捕获的运行时错误无效。
- iris 默认 panic 会返回 500 响应,但跳过所有
OnErrorCode注册函数 - 要统一处理 panic,必须用
app.UseRouter(recovery.New())(需引入github.com/kataras/iris/v12/middleware/recovery) - 若同时用了
recovery和OnErrorCode(500),注意二者顺序:recovery必须在前,否则 panic 会直接终止请求
真正容易被忽略的是:OnErrorCode 不是错误日志开关,也不是兜底渲染器。它只响应你亲手写的 StatusCode 调用 —— 这个隐含契约,决定了你得在业务逻辑里主动“抛出”状态码,而不是等着框架“捕获”错误。











