最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用gorm.Scopes函數(shù)實(shí)現(xiàn)復(fù)用查詢邏輯示例

 更新時(shí)間:2023年12月19日 12:00:18   作者:Go學(xué)堂  
這篇文章主要為大家介紹了使用gorm.Scopes函數(shù)實(shí)現(xiàn)復(fù)用查詢邏輯示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

今天要學(xué)習(xí)的是gorm.Scopes函數(shù)的使用。該函數(shù)的作用就是復(fù)用查詢條件。

gorm Scopes是什么

在項(xiàng)目中,你一定會(huì)遇到過很多需要復(fù)用的查詢條件。比如常用的場景有分頁、查詢時(shí)判定數(shù)據(jù)權(quán)限等操作。

比如,我們有兩個(gè)數(shù)據(jù)資源:用戶列表和部門列表。那么,在查詢列表的時(shí)候都會(huì)涉及到分頁。當(dāng)然可以在每個(gè)列表中都增加上列表相關(guān)的查詢。同時(shí),也可以將分頁的查詢抽取出來,做成公共的函數(shù)。

那怎么將抽取出來的分頁條件在每個(gè)列表中都能復(fù)用呢?那就是使用gorm.Scopes函數(shù)。

我們先看一個(gè)使用gorm.Scopes函數(shù)使用的簡單例子,這個(gè)例子只是為了說明gorm.Scopes函數(shù)的使用。如下:

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)
  }
}
// 查找所有金額大于 1000 的信用卡訂單
db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// 查找所有金額大于 1000 的 COD 訂單
db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
// 查找所有金額大于1000 的已付款或已發(fā)貨訂單
db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)

通過上述例子可以知道,前4個(gè)函數(shù)都是func (db *gorm.DB) *gorm.DB 類型的函數(shù),即輸入一個(gè)db,然后返回一個(gè)db。在該函數(shù)中的業(yè)務(wù)邏輯其實(shí)就是最常見的db.Where、db.Offset等常用的查詢條件語句而已。只不過是對這種公共的查詢語句進(jìn)行了提取并進(jìn)行復(fù)用而已。

然后將這樣的函數(shù)傳遞給Scopes。Scopes函數(shù)只是簡單的將func (db *gorm.DB) *gorm.DB放到Statement.scopes這個(gè)切片中。

最后,在最終執(zhí)行的時(shí)候,會(huì)循環(huán)遍歷Statement.scopes切片,依次執(zhí)行該切片中的每一個(gè)func (db *gorm.DB) *gorm.DB函數(shù)。這樣,就把提取出來的公共的查詢條件融合在一起了。

使用場景1 -- 分頁

當(dāng)然,我們在查詢時(shí)最常用的就是分頁功能。那么,如何使用gorm.Scopes實(shí)現(xiàn)分頁查詢的復(fù)用呢。如下:

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 = 100
    case pageSize <= 0:
      pageSize = 10
    }
    offset := (page - 1) * pageSize
    return db.Offset(offset).Limit(pageSize)
  }
}
db.Scopes(Paginate(r)).Find(&users)
db.Scopes(Paginate(r)).Find(&articles)

你看,先定義了一個(gè)分頁的函數(shù)Paginate函數(shù),該函數(shù)接收一個(gè)*http.Request參數(shù),然后返回一個(gè)func(db *gorm.DB) *gorm.DB的函數(shù)。因?yàn)?code>gorm.Scopes函數(shù)只接受func(db *gorm.DB) *gorm.DB類型的函數(shù)。最后,將Paginate函數(shù)傳遞給Scopes函數(shù)即可。

使用場景2 -- 數(shù)據(jù)權(quán)限

在go-admin開源項(xiàng)目中,我們還發(fā)現(xiàn)了一個(gè)典型的應(yīng)用,就是數(shù)據(jù)權(quán)限。在我們的系統(tǒng)中,會(huì)遇到這樣的場景:一些數(shù)據(jù)只能自己查看或操作;或者你的上級也能查看或操作;或者同部門的人員能查看或操作自己部門的數(shù)據(jù),但不能查看或操作其他部門的權(quán)限;又或者只能查看同部門的數(shù)據(jù)但不能操作同部門的數(shù)據(jù)等等。

在go-admin中,就使用了gorm.Scopes函數(shù)來統(tǒng)一使用權(quán)限查詢條件。在每個(gè)操作中,都通過Scopes函數(shù)傳入了一個(gè)Permission函數(shù)。Permissioin函數(shù)是根據(jù)不同角色擁有的權(quán)限,轉(zhuǎn)換成對應(yīng)的sql語句。如下:

// DeleteAction 通用刪除動(dòng)作
func DeleteAction(control dto.Control) gin.HandlerFunc {
 return func(c *gin.Context) {
  db, err := pkg.GetOrm(c)
        ...//省略了一些邏輯
  //數(shù)據(jù)權(quán)限檢查
  p := GetPermissionFromContext(c)
        // 將Permission函數(shù)傳入Scopes函數(shù)
  db = db.WithContext(c).Scopes(
   Permission(object.TableName(), p),
  ).Where(req.GetId()).Delete(object)
        ...//省略了一些邏輯
        // 檢查操作的行數(shù),如果操作的行數(shù)是0,說明沒有權(quán)限
  if db.RowsAffected == 0 {
   response.Error(c, http.StatusForbidden, nil, "無權(quán)刪除該數(shù)據(jù)")
   return
  }
  response.OK(c, object.GetId(), "刪除成功")
  c.Next()
 }
}
// Permission函數(shù)的邏輯
// 根據(jù)不同 的數(shù)據(jù)范圍枚舉值,轉(zhuǎn)換成不同的Where條件
func Permission(tableName string, p *DataPermission) func(db *gorm.DB) *gorm.DB {
 return func(db *gorm.DB) *gorm.DB {
  if !config.ApplicationConfig.EnableDP {
   return db
  }
  switch p.DataScope {
  case "2":
   return db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", p.RoleId)
  case "3":
   return db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", p.DeptId)
  case "4":
   return db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%/"+pkg.IntToString(p.DeptId)+"/%")
  case "5":
   return db.Where(tableName+".create_by = ?", p.UserId)
  default:
   return db
  }
 }
}

總結(jié)

gorm Scopes是一個(gè)非常強(qiáng)大的特性,它可以讓你復(fù)用你的邏輯,在查詢時(shí)實(shí)現(xiàn)更為復(fù)雜的查詢邏輯。在使用gorm Scope時(shí),你需要定義一個(gè)Scope函數(shù),并在查詢時(shí)應(yīng)用它。Scope函數(shù)可以被鏈?zhǔn)秸{(diào)用,并且可以接收參數(shù)。學(xué)習(xí)并掌握這個(gè)特性將會(huì)使你在編寫gorm查詢時(shí)事半功倍。

以上就是使用gorm.Scopes函數(shù)實(shí)現(xiàn)復(fù)用查詢邏輯示例的詳細(xì)內(nèi)容,更多關(guān)于gorm.Scopes復(fù)用查詢邏輯的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文帶你使用Golang實(shí)現(xiàn)SSH客戶端

    一文帶你使用Golang實(shí)現(xiàn)SSH客戶端

    SSH?全稱為?Secure?Shell,是一種用于安全地遠(yuǎn)程登錄到網(wǎng)絡(luò)上的其他計(jì)算機(jī)的網(wǎng)絡(luò)協(xié)議,本文主要為大家詳細(xì)介紹了如何使用?Golang?實(shí)現(xiàn)?SSH?客戶端,需要的可以參考下
    2023-11-11
  • 淺談Go語言多態(tài)的實(shí)現(xiàn)與interface使用

    淺談Go語言多態(tài)的實(shí)現(xiàn)與interface使用

    如果大家系統(tǒng)的學(xué)過C++、Java等語言以及面向?qū)ο蟮脑?,相信?yīng)該對多態(tài)不會(huì)陌生。多態(tài)是面向?qū)ο蠓懂牣?dāng)中經(jīng)常使用并且非常好用的一個(gè)功能,它主要是用在強(qiáng)類型語言當(dāng)中,像是Python這樣的弱類型語言,變量的類型可以隨意變化,也沒有任何限制,其實(shí)區(qū)別不是很大
    2021-06-06
  • golang如何利用原始套接字構(gòu)造UDP包詳解

    golang如何利用原始套接字構(gòu)造UDP包詳解

    這篇文章主要給大家介紹了關(guān)于golang如何利用原始套接字構(gòu)造UDP包的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-10-10
  • golang判斷key是否在map中的代碼

    golang判斷key是否在map中的代碼

    這篇文章主要介紹了golang判斷key是否在map中的代碼,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 基于Go語言實(shí)現(xiàn)插入排序算法及優(yōu)化

    基于Go語言實(shí)現(xiàn)插入排序算法及優(yōu)化

    插入排序是一種簡單的排序算法。這篇文章將利用Go語言實(shí)現(xiàn)冒泡排序算法,文中的示例代碼講解詳細(xì),對學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2022-12-12
  • 深入了解Golang為什么需要超時(shí)控制

    深入了解Golang為什么需要超時(shí)控制

    本文將介紹為什么需要超時(shí)控制,然后詳細(xì)介紹Go語言中實(shí)現(xiàn)超時(shí)控制的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-05-05
  • golang gorm 操作mysql及gorm基本用法

    golang gorm 操作mysql及gorm基本用法

    golang 官方的那個(gè)操作mysql的有點(diǎn)麻煩所以就使用了gorm,下面就gorm的使用做下簡單介紹,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • Golang與其他語言不同的九個(gè)特性

    Golang與其他語言不同的九個(gè)特性

    近來關(guān)于對Golang的討論有很多,七牛的幾個(gè)大牛們也斷定Go語言在未來將會(huì)快速發(fā)展,并且很可能會(huì)取代Java成為互聯(lián)網(wǎng)時(shí)代最受歡迎的編程語言。本文將帶你了解它不同于其他語言的九個(gè)特性
    2021-09-09
  • go語言中的結(jié)構(gòu)體嵌入詳解(最新推薦)

    go語言中的結(jié)構(gòu)體嵌入詳解(最新推薦)

    結(jié)構(gòu)體嵌入是Go語言中的一種特性,允許在一個(gè)結(jié)構(gòu)體中包含另一個(gè)結(jié)構(gòu)體,從而實(shí)現(xiàn)代碼復(fù)用和方法復(fù)用,嵌入結(jié)構(gòu)體的字段和方法會(huì)被提升到外部結(jié)構(gòu)體中,可以直接訪問,本文給大家介紹go語言中的結(jié)構(gòu)體嵌入的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Golang重構(gòu)wget腳本構(gòu)建通用并發(fā)下載工具的實(shí)踐指南

    Golang重構(gòu)wget腳本構(gòu)建通用并發(fā)下載工具的實(shí)踐指南

    在當(dāng)今的開發(fā)和運(yùn)維工作中,大文件批量下載是一個(gè)常見需求,本文分享如何用Golang構(gòu)建一個(gè)通用高效的并發(fā)下載工具,有需要的小伙伴可以了解下
    2025-11-11

最新評論

宣化县| 什邡市| 肥乡县| 崇州市| 嘉义县| 云和县| 大田县| 公主岭市| 咸宁市| 鄂州市| 克什克腾旗| 乌兰察布市| 宁津县| 昌乐县| 北宁市| 临洮县| 宁化县| 化隆| 炉霍县| 大安市| 革吉县| 凤凰县| 永年县| 怀集县| 广河县| 望江县| 广南县| 尚义县| 阜新市| 稻城县| 泽普县| 方正县| 兴化市| 新化县| 普格县| 三穗县| 手游| 巩义市| 崇州市| 扶绥县| 华池县|