Pattern: Build SQL fragments + struct holding all possible parameters. Use @FieldName placeholders—GORM matches exported struct fields.
type MerchBill struct { ID uint`gorm:"primarykey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` Applyno string`gorm:"column:applyno;type:varchar(255);comment:订单号;"` }
funcgetList(info req.Mer) (err error, list interface{}, total int64) { db := DB.Model(&MerchBill{}) // assume DB is *gorm.DB
var bills []MerchBill var countWrap []struct{ Countnum int64 }
baseSelect := "SELECT bill.*, mer.mobile, mer.merchname" baseCount := "SELECT COUNT(*) AS countnum" whereSql := " FROM billtable AS bill LEFT JOIN merch_user AS mer ON mer.id = bill.merchid WHERE 1"
var param struct { Applyno string Status *int Applytype *int Applyrealname string Merchname string Limit int Offset int }
if info.Applyno != "" { whereSql += " AND bill.applyno = @Applyno" param.Applyno = info.Applyno } if info.Status != nil { whereSql += " AND bill.status = @Status" param.Status = info.Status } if info.Applytype != nil { whereSql += " AND bill.applytype = @Applytype" param.Applytype = info.Applytype } if info.Applyrealname != "" { whereSql += " AND bill.applyrealname = @Applyrealname" param.Applyrealname = info.Applyrealname } if info.Merchname != "" { whereSql += " AND mer.merchname LIKE @Merchname" param.Merchname = info.Merchname }
orderLimit := " ORDER BY bill.id DESC LIMIT @Offset,@Limit" param.Limit = info.PageSize param.Offset = info.PageSize * (info.Page - 1)
if err = db.Raw(baseSelect+whereSql+orderLimit, param).Scan(&bills).Error; err != nil { return } if err = db.Raw(baseCount+whereSql, param).Scan(&countWrap).Error; err != nil { return } total = countWrap[0].Countnum return err, bills, total }
Tips:
Always export struct fields (capitalized) for binding.
Keep one param struct—unused fields are ignored.
Use IN (@Param) style only with slices supported; for complex dynamic lists, build placeholders explicitly.