GORM docs: https://gorm.io/docs/sql_builder.html

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:订单号;"`
}

func getList(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:

  1. Always export struct fields (capitalized) for binding.
  2. Keep one param struct—unused fields are ignored.
  3. Use IN (@Param) style only with slices supported; for complex dynamic lists, build placeholders explicitly.