iris mvc不自动处理controller返回的error,必须手动中断流程;推荐用ctx.statuscode()+ctx.json()+ctx.stopwithstatus()+return四步组合确保正确响应。

Controller返回的error不会被自动捕获
Iris MVC层完全不处理controller方法返回的error——无论你写func(c *UserCtrl) GetByID(id int64) (string, error)还是func(c *UserCtrl) GetByID(id int64) error,框架都视而不见,请求会继续执行、状态码默认200、响应体可能为空或乱序。这是最常被误以为“框架会兜底”的坑。
必须主动中断流程:要么用panic(&BizError{...})触发recover,要么用ctx.StopWithStatus()显式终止。
- 返回
error仅适用于你想让上层(比如中间件)统一处理的场景,但Iris没提供该能力,所以实际无效 - 想靠
return errors.New("xxx")让框架自动生成400响应?不行,它只会当普通返回值忽略 - 所有业务校验失败、DB错误、参数非法,都得走手动中断路径
两种中断方式怎么选:panic vs StopWithStatus
panic写法短,但掩盖了控制流;StopWithStatus更清晰,但容易漏掉return导致后续逻辑意外执行。
推荐用StopWithStatus组合:ctx.StatusCode() + ctx.JSON() + ctx.StopWithStatus() + return,四者缺一不可。
-
ctx.StatusCode(400)设状态码,否则浏览器收到200会缓存错误响应 -
ctx.JSON(BizError{...})输出结构化错误体 -
ctx.StopWithStatus(400)立即终止当前handler,但不阻止中间件After逻辑 - 后面必须跟
return,否则user, err := c.Service.FindByID(id)仍会执行
示例:
func (c *UserController) GetByID(id int64) {
if id
<h3>全局recover只能捕获panic,不能替代StopWithStatus</h3>
<p>你在<code>app.Use()</code>里写的recover中间件,只对<code>panic(&BizError{...})</code>生效,对正常返回、<code>ctx.JSON()</code>调用、甚至<code>ctx.StopExecution()</code>都无反应。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5"><img
src="https://img.php.cn/upload/manual/001/589/237/6aa35e21a9024187.png" alt="Iris框架 12.2.5" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5" class="overflowclass">Iris框架 12.2.5</a>
<p class="overflowclass">Iris框架 12.2.5 版本源码包下载,适合需要 MVC Singleton 控制器、依赖注入字段控制和 debug 错误日志改进的开发者。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>这意味着:如果你混合使用两种错误抛出方式(一部分用panic,一部分用StopWithStatus),recover中间件只覆盖前者,后者仍需各自保证<code>return</code>和状态码正确。</p>
- recover中间件里别直接
ctx.JSON(),应先判断r类型是否为*BizError,避免把系统panic(如nil pointer)也当成业务错误返回 - recover无法补救
StopWithStatus漏掉return导致的重复DB操作——这类bug只能靠代码审查或单元测试暴露 - 不要在recover里调用
ctx.Next(),它已无意义;panic后控制流已跳出当前中间件链
BizError结构体必须实现Error()方法
如果你打算用recover统一处理,BizError必须有Error()方法,否则recover()拿到的是&{40001 "xxx" nil}这种默认字符串,无法做类型断言。
定义时务必包含:
func (e *BizError) Error() string {
return fmt.Sprintf("[%d]%s", e.Code, e.Msg)
}
否则if r := recover(); r != nil { if bizErr, ok := r.(*BizError); ok { ... } }里的ok永远为false。
这个细节极容易被跳过,结果就是panic全被当成未知错误打日志,前端收不到code字段。










