Iris路由层通过宏函数在匹配阶段校验参数,如{id:int min(1) max(999999)};若未生效常见原因包括未写宏、未注册自定义宏或语法错误;Controller层需手动判断边界,防范零值陷阱。

路由层校验:用宏函数在匹配阶段拦截非法参数
Iris 的 MVC 不自动校验控制器方法的入参,但路由注册时就能拦住明显错误——靠宏函数。比如 {id:int min(1) max(999999)} 这种写法,不是装饰器,是 Iris 在 radix tree 匹配时就执行的硬规则。
常见错误现象:请求 /order/0 或 /order/1000000 却进了 handler,说明宏没生效。原因通常是:
- 没在路由字符串里写宏,只写了
{id},没加:int min(1) - 用了自定义宏但忘了调用
app.Macros().Register注册 - 宏语法拼错,比如写成
min1而非min(1),Iris 会静默忽略整段宏
性能影响很小,因为这是纯字符串匹配阶段的判断,不进 handler 就不耗业务逻辑资源。
Controller 层校验:手动取参 + 显式判断边界
MVC 控制器方法签名里的参数(如 id int64)只是 Go 类型声明,Iris 不做范围校验。你得自己写 if 判断,尤其注意零值陷阱:
-
id int64参数默认是 0,但 0 往往非法,必须显式if id -
page, size int必须检查page >= 1和size > 0 && size ,否则分页可能查全表 - 用
c.Ctx.URLParamInt("page")比直接依赖方法签名更可控,因为能拿到 error 并区分“没传”和“传了非数字”
别指望框架帮你挡掉 ?page=-5&size=abc 这类请求——URLParamInt 返回 error,你不 check 就 panic。
结构体绑定校验:JSON/Form 提交需配合第三方库
Iris 默认不校验结构体字段,ctx.ReadJSON(&req) 成功只代表 JSON 格式合法,字段值是否符合业务规则得你来定。
推荐做法是用 go-playground/validator 配合 tag:
type CreateUserReq struct {
Name string `json:"name" validate:"required,min=2,max=20"`
Email string `json:"email" validate:"required,email"`
}
然后在 controller 里手动校验:
var req CreateUserReq
if err := c.Ctx.ReadJSON(&req); err != nil {
c.Ctx.StatusCode(400)
c.Ctx.JSON(BizError{Code: 40002, Msg: "参数格式错误"})
c.Ctx.StopWithStatus(400)
return
}
if err := validator.New().Struct(req); err != nil {
c.Ctx.StatusCode(400)
c.Ctx.JSON(BizError{Code: 40003, Msg: "参数校验失败"})
c.Ctx.StopWithStatus(400)
return
}
容易踩的坑:validator 的 tag 写错(比如 valid:"required" 少了 a),或没 import validator 包导致编译不过;还有人把校验逻辑写在中间件里,结果 controller 仍收到非法数据——校验必须在 ReadJSON 之后、业务逻辑之前。
错误响应统一处理:StopWithStatus 是关键开关
无论在哪一层校验失败,都必须调用 c.Ctx.StopWithStatus(statusCode) 并紧跟 return,否则 controller 方法会继续往下跑。
典型错误写法:
if id <= 0 {
c.Ctx.StatusCode(400)
c.Ctx.JSON(BizError{...})
// 忘了 StopWithStatus 和 return → 后面代码照常执行!
}
user, err := c.Service.FindByID(id) // 这里 panic
真正生效的写法只有这一种顺序:
- 设状态码 →
- 写响应体 →
- 调
StopWithStatus→ - 立即
return
这个链条断任何一环,校验就形同虚设。StopWithStatus 不是装饰,是强制中断执行流的指令。


















