go 整数的默认值0不传也是查询的解决方法

Go 中整数字段的零值是0,这在数据库查询时确实是个常见问题:当你想"不传就不查询"时,0会被当成有效条件传入,导致查询结果不符合预期。

以下是几种常见的解决方法:

传-1

if self.Query.TrainStatus >= 0 && userId > 0 { if self.Query.TrainStatus == 0 { // 未开始:要么 musp 不存在,要么 musp.train_status=0 joinQuery.WithWhere("(musp.train_status IS NULL OR musp.train_status = 0)") } else { // 其他状态:必须 musp 存在且 musp.train_status 等于指定值 joinQuery.WithWhere("musp.train_status = ?", int(self.Query.TrainStatus)) } }

1. 使用指针类型*int

最通用的做法,用nil表示"未设置":

go

type QueryParams struct { Status *int `form:"status"` // 不传时为 nil,传 0 时 &0 } func query(db *gorm.DB, params QueryParams) *gorm.DB { if params.Status != nil { db = db.Where("status = ?", *params.Status) } return db }

优点:语义清晰,能区分"未传"和"传了 0"。
缺点:使用稍繁琐,需要解引用。


2. 使用sql.NullInt64/sql.NullInt32

适合数据库交互场景:

go

type QueryParams struct { Status sql.NullInt64 `form:"status"` } func query(db *gorm.DB, params QueryParams) *gorm.DB { if params.Status.Valid { db = db.Where("status = ?", params.Status.Int64) } return db }

优点:与 SQL 生态兼容,明确表达"有值/无值"。


3. 配合自定义 Tag + 反射的通用方案

如果字段很多,不想每个都写if,可以用反射封装:

go

type QueryParams struct { Status int `form:"status" zero:"ignore"` // 自定义 tag Age int `form:"age" zero:"ignore"` } func BuildQuery(db *gorm.DB, model interface{}) *gorm.DB { // 反射遍历字段,遇到 zero:"ignore" 且为零值则跳过 // ... }

4. 用特殊值约定(不推荐但简单)

比如用-1表示"全部/不限":

go

type QueryParams struct { Status int `form:"status" binding:"gte=-1"` } func query(db *gorm.DB, status int) *gorm.DB { if status != -1 { db = db.Where("status = ?", status) } return db }

缺点:语义不直观,容易踩坑。


5. 如果用的是 GORM,配合map条件

go

func query(db *gorm.DB, status int) *gorm.DB { cond := map[string]interface{}{} if status != 0 { // 或根据业务判断 cond["status"] = status } return db.Where(cond) }

推荐方案

表格

场景推荐
简单查询、字段少指针*int
大量查询条件、通用封装反射 + 自定义 tag
与数据库模型强绑定sql.NullInt64

你目前用的是哪个框架(Gin + GORM?还是标准库)?我可以给更贴合你项目的代码。

最优解,尽量不取0值!