iris中controller返回error被忽略,错误响应须显式调用ctx.stopwithstatus()终止流程;单独statuscode()或json()无效,顺序错误会导致响应异常。

必须手动中断,Iris不会自动拦截controller返回的error
在Iris中,Controller方法返回error值完全被忽略——框架既不捕获、也不响应。这意味着写return errors.New("xxx")或return fmt.Errorf("...")对HTTP状态码和响应体毫无影响。所有错误响应必须显式构造并终止执行流。
用ctx.StopWithStatus()强制终止请求
这是最可控、最推荐的方式。它明确设置状态码、写入JSON、并立即停止后续中间件和handler执行。
-
ctx.StatusCode()只设状态码,不阻断流程;必须配合ctx.StopWithStatus() -
ctx.JSON()只序列化数据,不设状态码;若之前没调用StatusCode(),默认是200 -
ctx.StopWithStatus(400)必须紧跟ctx.JSON()之后,且后面要跟return,否则controller剩余逻辑仍会执行
示例:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
func (c *ProductController) Create(ctx iris.Context) {
var req ProductReq
if err := ctx.ReadJSON(&req); err != nil {
ctx.StatusCode(400)
ctx.JSON(BizError{Code: 40001, Msg: "参数解析失败"})
ctx.StopWithStatus(400)
return // ⚠️ 必须有
}
// ... 正常逻辑
}
用panic(&BizError{})触发recover捕获
适合快速兜底,但掩盖了控制流,调试困难,不建议在核心路径使用。
- 必须提前注册
recover()中间件,且只捕获panic,对普通return error无效 -
BizError类型必须实现Error()方法,否则recover()拿到的是interface{},无法类型断言 - panic会跳过defer链中未执行的部分(如DB事务rollback),存在资源泄漏风险
中间件示例:
app.Use(func(ctx iris.Context) {
defer func() {
if r := recover(); r != nil {
switch e := r.(type) {
case *BizError:
ctx.StatusCode(500)
ctx.JSON(e)
default:
ctx.StatusCode(500)
ctx.JSON(BizError{Code: 50000, Msg: "未知系统错误"})
}
}
}()
ctx.Next()
})
别踩ctx.StatusCode()单独使用的坑
单独调用ctx.StatusCode(400)不会改变响应体,也不会阻止后续逻辑。常见错误现象是:前端收到200 OK但body为空,或收到200 OK却带了错误JSON。
- 状态码和响应体必须成对出现,且
StopWithStatus是唯一能确保“写完就停”的API - 不要依赖
ctx.SetStatusCode()——它只是内部标记,不影响输出行为 - 测试时务必检查实际HTTP响应的状态码,不能只看JSON内容
最易被忽略的一点:StopWithStatus不是“设置状态码并停止”,而是“以该状态码结束本次响应”。它会清空已写入的header和body缓冲区,所以必须在JSON()之后立即调用,顺序错乱会导致响应异常。










