ctx.statuscode() 必须显式调用,否则 json 响应默认为 200;iris 不自动设状态码,需在 ctx.json 前调用 ctx.statuscode;onerrorcode 仅处理未匹配路由的全局 404,不替代业务层错误处理。

ctx.StatusCode() 必须显式调用,否则 JSON 响应永远是 200
很多人写 ctx.JSON(iris.Map{"error": "not found"}) 就以为返回了 404,结果前端看到状态码仍是 200 —— 这会导致错误无法被 Axios 或 Fetch 的 response.ok 拦截,前端逻辑全乱。Iris 不会根据响应内容自动设状态码,ctx.JSON 只负责序列化和写入,状态码必须提前或同步设置。
-
ctx.StatusCode(iris.StatusNotFound)要在ctx.JSON(...)之前或同一逻辑块中调用 - 推荐封装统一错误响应函数,比如
writeError(ctx, iris.StatusUnauthorized, "token expired"),避免漏设 - 中间件里拦截 panic 后,也要手动调用
ctx.StatusCode(iris.StatusInternalServerError),不能只写 JSON
OnErrorCode 是全局错误兜底,不是路由级 404 处理
app.OnErrorCode(iris.StatusNotFound, handler) 注册的是整个应用级别的“未匹配到任何路由”后的最终响应逻辑,它不替代路由定义本身。也就是说:只有当所有 app.Get/app.Post 等都查不到匹配路径时,才会触发这个 handler;它不会捕获 handler 内部主动写的 404(比如数据库查不到用户),那类错误仍需你自己处理并返回。
- 该 handler 适合做统一错误页渲染(如 HTML 404 页面)或日志记录,不适合做业务逻辑判断
- 若想对某类资源缺失返回定制 JSON,应在对应路由 handler 中自己判断并调用
ctx.StatusCode + ctx.JSON - 注意:
OnErrorCodehandler 执行时,请求上下文已离开原路由,ctx.Values()中的临时数据可能已被清理
自定义错误类型要和 HTTP 状态码、JSON 字段对齐
直接用 errors.New("xxx") 或 fmt.Errorf 返回错误,在 Iris 中只是原始 error 值,不会自动转成 HTTP 状态码或结构化 JSON。要让错误可预测、可分类、前端可解析,得靠业务层封装。
- 定义带错误码的结构体,例如
type BizError struct { Code int `json:"code"` Msg string `json:"msg"` } - 在 handler 中用
ctx.StatusCode(err.Code); ctx.JSON(err)统一输出,而非拼字符串 - 避免把敏感信息(如 DB 错误详情)直接透出到 JSON 响应中,生产环境应做脱敏
- 如果用了
iris.Map临时构造错误响应,确保字段名与前端约定一致(如统一用message而非msg或error)
时间字段和空值容易引发前端解析失败
Go 的 time.Time 默认 JSON 序列化为 RFC3339 字符串(如 "2026-10-09T01:15:00Z"),而很多前端库默认期待 Unix 时间戳或 MySQL 格式;同样,零值字段(如 int 为 0、string 为空)若没加 omitempty,会污染响应结构。
- 对时间字段,要么加
json:"created_at,string"强制转字符串(但仍是 RFC3339),要么实现自定义MarshalJSON方法输出毫秒时间戳 - 数值型字段若业务上 “0” 和 “未提供” 含义不同,必须用指针类型(如
*int)+omitempty,否则无法区分 - 错误响应中的时间字段(如
timestamp)建议统一用time.Now().UTC().Format(time.RFC3339)显式控制格式,别依赖结构体字段自动序列化
iris.Compression,错误 JSON 也会被压缩;如果你设置了全局 ctx.Header("X-Content-Type-Options", "nosniff"),它也生效。错误处理不是隔离区,而是整个 HTTP 流程的一部分。











