作用域允许你复用通用的逻辑,这种共享逻辑需要定义为类型func(*gorm.DB) *gorm.DB。
查询
Scope 查询示例:
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {return db.Where("amount > ?", 1000)}func PaidWithCreditCard(db *gorm.DB) *gorm.DB {return db.Where("pay_mode_sign = ?", "C")}func PaidWithCod(db *gorm.DB) *gorm.DB {return db.Where("pay_mode_sign = ?", "C")}func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {return func (db *gorm.DB) *gorm.DB {return db.Where("status IN (?)", status)}}db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)// 查找所有金额大于 1000 的信用卡订单db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)// 查找所有金额大于 1000 的 COD 订单db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)// 查找所有金额大于1000 的已付款或已发货订单
分页
func Paginate(r *http.Request) func(db *gorm.DB) *gorm.DB {return func (db *gorm.DB) *gorm.DB {q := r.URL.Query()page, _ := strconv.Atoi(q.Get("page"))if page <= 0 {page = 1}pageSize, _ := strconv.Atoi(q.Get("page_size"))switch {case pageSize > 100:pageSize = 100case pageSize <= 0:pageSize = 10}offset := (page - 1) * pageSizereturn db.Offset(offset).Limit(pageSize)}}db.Scopes(Paginate(r)).Find(&users)db.Scopes(Paginate(r)).Find(&articles)
动态表
使用 Scopes 来动态指定查询的表
func TableOfYear(user *User, year int) func(db *gorm.DB) *gorm.DB {return func(db *gorm.DB) *gorm.DB {tableName := user.TableName() + strconv.Itoa(year)return db.Table(tableName)}}DB.Scopes(TableOfYear(user, 2019)).Find(&users)// SELECT * FROM users_2019;DB.Scopes(TableOfYear(user, 2020)).Find(&users)// SELECT * FROM users_2020;// Table form different databasefunc TableOfOrg(user *User, dbName string) func(db *gorm.DB) *gorm.DB {return func(db *gorm.DB) *gorm.DB {tableName := dbName + "." + user.TableName()return db.Table(tableName)}}DB.Scopes(TableOfOrg(user, "org1")).Find(&users)// SELECT * FROM org1.users;DB.Scopes(TableOfOrg(user, "org2")).Find(&users)// SELECT * FROM org2.users;
更新
Scope 更新、删除示例:
func CurOrganization(r *http.Request) func(db *gorm.DB) *gorm.DB {return func (db *gorm.DB) *gorm.DB {org := r.Query("org")if org != "" {var organization Organizationif db.Session(&Session{}).First(&organization, "name = ?", org).Error == nil {return db.Where("org_id = ?", organization.ID)}}db.AddError("invalid organization")return db}}db.Model(&article).Scopes(CurOrganization(r)).Update("Name", "name 1")// UPDATE articles SET name = "name 1" WHERE org_id = 111db.Scopes(CurOrganization(r)).Delete(&Article{})// DELETE FROM articles WHERE org_id = 111