Iris 的 MVC 不原生支持条件查询自动绑定,需用指针字段(如 *string)区分“未提供”与“零值”,配合 ReadQuery 显式判空构建 SQL 条件,并手动处理多值、分页、时间范围及安全校验。

Iris 的 MVC 并不原生支持“条件查询”这种业务逻辑的自动绑定——它只负责把请求参数映射到 struct 字段,真正的条件拼接、SQL 构建或 ORM 查询必须手动写。
为什么不能直接用 iris.Context.ReadForm 绑定动态条件
常见误区是以为给一个 struct 填上 json 或 form tag 就能自动过滤空字段做 WHERE 条件。但 ReadForm 会把所有字段(包括零值)都塞进去,比如 Age int `form:"age"` 传空字符串时变成 0,你没法区分“用户没填 age”和“用户明确查 age=0”。
- 空字符串、
0、false都会被当成有效条件参与 SQL 拼接 - 没有字段级的“是否启用该条件”的元信息
- 无法表达
LIKE %keyword%、IN (1,2,3)、created_at > ?这类非等值条件
推荐做法:用指针字段 + 显式判空
让每个可选查询字段声明为指针类型,这样 nil 表示“未提供”,非 nil 才参与条件构建。配合 gorilla/schema 或 Iris 自带的 ReadQuery / ReadForm 可以安全解包。
// 查询参数结构体
type UserSearch struct {
Name *string `form:"name"`
Age *int `form:"age"`
Active *bool `form:"active"`
}
func (c *UserController) GetUsers(ctx iris.Context) {
var search UserSearch
if err := ctx.ReadQuery(&search); err != nil {
ctx.StatusCode(400)
ctx.JSON(iris.Map{"error": "invalid query"})
return
}
// 构建 GORM 条件(示例)
db := c.app.DB // 假设已注入 *gorm.DB
query := db.Model(&User{})
if search.Name != nil && *search.Name != "" {
query = query.Where("name LIKE ?", "%"+*search.Name+"%")
}
if search.Age != nil {
query = query.Where("age = ?", *search.Age)
}
if search.Active != nil {
query = query.Where("active = ?", *search.Active)
}
var users []User
query.Find(&users)
ctx.JSON(users)
}
- 必须用
*string、*int、*bool,不能用值类型 -
ReadQuery对指针字段能正确处理缺失/空值(不会 panic,也不会赋默认零值) - 注意
*search.Name != ""要先判 nil 再解引用,否则 panic
如何支持多值条件(如 status IN (1,2))
Iris 默认不解析逗号分隔的 query 参数为 slice,需要手动拆解或改用 []string + 自定义绑定。
- 前端传
?status=1&status=2&status=3→ 后端用[]string接收,ReadQuery原生支持 - 前端传
?status=1,2,3→ 用ctx.URLParam("status")拿原始字符串,再strings.Split - GORM 中用
Where("status IN ?", statuses),注意statuses是[]interface{}类型切片
例如:
statusesStr := ctx.URLParam("status")
if statusesStr != "" {
statuses := strings.Split(statusesStr, ",")
var statusInts []interface{}
for _, s := range statuses {
if i, err := strconv.Atoi(s); err == nil {
statusInts = append(statusInts, i)
}
}
if len(statusInts) > 0 {
query = query.Where("status IN ?", statusInts)
}
}
容易被忽略的边界点
条件查询真正难的不是语法,而是语义一致性:
- 前端传
page=0还是page=1?Iris 不管分页逻辑,你要统一约定并校验 -
time_start和time_end传了其中一个但没传另一个?得补默认范围(如 1970-01-01 或 now) - 用户输入 SQL 注入字符(如
name=%'; DROP TABLE users; --)?GORM 的Where占位符是安全的,但手拼 SQL 就危险 - 大量 OR 条件导致全表扫描?记得在数据库加复合索引,而不是只依赖代码层
别指望框架替你决定“哪些字段该进 WHERE”,这事必须由你逐个判断、逐个加 guard。


















