gorm用struct查询时零值字段(0、""、false)被自动忽略,导致age=0等条件丢失;count()必须传int64指针且model()需置于where前,否则查不到数据或编译失败。

零值字段(0、""、false)在 struct 查询中会被 GORM 自动忽略,这不是 bug,但极易导致查不到数据——必须用 map[string]interface{} 或字符串条件显式表达零值。
Why struct 传参查不到 age = 0 的记录
GORM 对 struct 做条件查询时,只取「非零值」字段生成 WHERE 子句:&User{Name: "Tom", Age: 0} 实际发出的 SQL 是 WHERE name = 'Tom',age = 0 被跳过。这和 Go 的零值语义一致,但业务里常有 status=0、is_active=0 等合法状态码,一用 struct 就丢条件。
- struct 中加
gorm:"default:0"没用——Where不读 struct tag,只看运行时值 - 哪怕字段是指针类型(如
*int),只要值为nil,照样被忽略 - 想查
deleted_at IS NULL?struct 写不出来,只能用字符串
Where 字符串写法必须用 ? 占位符
手拼 SQL 字符串(如 "name = '" + input + "'")会引发 SQL 注入,GORM 明确要求用 ? 占位,由驱动做参数化绑定。
-
db.Where("age > ? AND status = ?", 18, 1)✅ 安全且清晰 -
db.Where("id IN ?", []uint{1,2,3})✅ 切片自动展开为(1,2,3);别写成?, ?, ? -
db.Where("name LIKE ?", "%"+keyword+"%")✅ 通配符自己加,GORM 不帮你补 -
db.Where("created_at BETWEEN ? AND ?", start, end)✅ 比手写两个>=和更易读
Or / Not 组合容易括号错乱
db.Where("age > ?", 18).Or("role = ?", "admin").Where("status = ?", 1) 生成的是 WHERE age > 18 OR role = 'admin' AND status = 1,因 AND 优先级高于 OR,实际等价于 age > 18 OR (role = 'admin' AND status = 1),不是你想要的逻辑。
- 正确做法:用嵌套
Where显式分组,例如db.Where("(age > ? OR role = ?) AND status = ?", 18, "admin", 1) - 或用
Scopes封装可复用的条件块,避免重复写括号 -
Not同理:db.Not("name = ?", "admin").Not("status = ?", 0)是 AND 关系,不是 OR
Count() 必须传 int64 指针,且 Model() 要放最前
Count() 是终值方法,返回 int64 并写入你传入的变量地址,不是链式调用的 *gorm.DB。
- 错误:
total := db.Where(...).Count()→ 编译失败,Count()没有返回值 - 错误:
db.Where(...).Count().Error→ 报错,Count()没有Error字段 - 正确:
var total int64; db.Model(&User{}).Where("status = ?", "active").Count(&total) -
Model(&User{})必须在Where前——否则 GORM 可能推导错表名,WHERE 字段找不到就报错
最易被忽略的是 struct 零值行为和 Count() 的指针传参:一个导致查不到数据却无报错,一个导致编译失败或统计恒为 0,两者都安静得让人摸不着头脑。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











