溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

golang中如何實現(xiàn)db事務(wù)的統(tǒng)一封裝

發(fā)布時間:2021-12-10 14:45:31 來源:億速云 閱讀:247 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下golang中如何實現(xiàn)db事務(wù)的統(tǒng)一封裝,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

    事務(wù)處理的流程示例

    database := db.DB
        tx, err := database.Begin()
        if err != nil {
            return err
        }
        stmt, err := tx.Prepare(sqlQuery)
        if err != nil {
            tx.Rollback()
            return err
        }
        _, err = stmt.Exec(paras...)
        if err != nil {
            tx.Rollback()
            return err
        }
        err = tx.Commit()
        if err != nil {
            tx.Rollback()
            return err
        }

    以上是我們使用事務(wù)時的一般操作,如果每做一次事務(wù)的操作均要進(jìn)行重新寫一遍代碼豈不是很麻煩,尤其是出錯時,Rollback需要多次在不同錯誤的地方的進(jìn)行調(diào)用處理。

    簡單封裝

    偷懶第一步

    采用defer處理Rollback

    defer tx.Rollback()

    無論成功與否,均進(jìn)行Rollback操作,只是有點影響,如果成功還調(diào)用Rollback的話,將會報錯。雖然可以忽略,但作為程序員,有必要進(jìn)一步調(diào)整。

    偷懶第二步

    根據(jù)執(zhí)行結(jié)果來選擇執(zhí)行Rollback,避免無效使用。

    defer func() { //根據(jù)執(zhí)行結(jié)果選擇執(zhí)行Rollback
            if err != nil && tx != nil {
            log.Println("ExecSqlWithTransaction defer err :", err)
                tx.Rollback()
            }
        }()

    如此,我們就可以根據(jù)事務(wù)的執(zhí)行結(jié)果決定是否Rollback了。

    偷懶第三步

    封裝,以上代碼本身就具有極大的普適性,因此,我們抽出通用的參數(shù),將此過程封裝成一個func,以后就可以直接調(diào)用了。

    func ExecSqlWithTransaction(database *sql.DB, query string, args ...interface{}) (err error) {
        tx, err := database.Begin()
        if err != nil {
            return err
        }
        defer func() {
            if err != nil && tx != nil {
                tx.Rollback()
            }
        }()
        stmt, err := tx.Prepare(query)
        if err != nil {
            return err
        }
        defer stmt.Close()
        _, err = stmt.Exec(args...)
        if err != nil {
            return err
        }
        return tx.Commit()
    }

    封裝后我們可以如下使用:

    if err := ExecSqlWithTransaction(database,sqlQuery,paras...);err != nil{
        //錯誤處理
    }

    封裝后是不是很簡潔???

    進(jìn)一步封裝

    在一個事務(wù)中可能會出現(xiàn)多個SELECT、UPDATE等操作,以上封裝僅處理了一種操作,還不能滿足我們的實際需求,因此需要更進(jìn)一步封裝。

    func ExecSqlWithTransaction(db *sql.DB, handle func(tx *sql.Tx) error) (err error) {
     tx, err := db.Begin()
     if err != nil {
      return err
     }
     defer func() {
      if err != nil {
       tx.Rollback()
      }
     }()
     if err = handle(tx); err != nil {
      return err
     }
     return tx.Commit()
    }

    在handle func內(nèi)可以直接使用事務(wù)tx進(jìn)行增刪改查。

    以上是“golang中如何實現(xiàn)db事務(wù)的統(tǒng)一封裝”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI