基於gin的golang web開發:使用數據庫事務


在前文介紹訪問數據庫時介紹了github.com/jmoiron/sqlx包,本文基於這個包使用數據庫事務。

defer

在使用數據庫事務之前,首先需要了解go語言的defer關鍵字。defer是go語言的延遲執行語句,defer后面的語句會被go進行延遲處理,在函數即將結束的時候,defer后面的語句將逆序執行。也就是說,先defer的語句最后執行。defer很像java或者C#中的finally語句。下面通過一個例子看一下defer。

package main

import "fmt"

func main() {
	fmt.Println("defer 開始")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	panic("測試 panic")
	fmt.Println("defer 結束")
}

代碼運行結果:

defer 開始
3
2
1
panic: 測試 panic

goroutine 1 [running]:
main.main()
	/tests/gookokok/main.go:10 +0x1b8

Process finished with exit code 2

通過運行結果可以看到defer的逆序輸出。在之后又手動觸發了一個panic,影響了最后一行的輸出defer 結束,go在觸發panic時優先執行了defer,足以證明defer是非常安全的,所以defer也常常被用來互斥解鎖、關閉文件或數據庫事務的處理。

事務

sqlx使用事務和database/sql相比擴展出了MustBegin()、MustExec()等方法,這樣就不需要在代碼中手動處理很多錯誤。MustBegin會在出現錯誤的時候觸發panic而不是返回錯誤,這樣就可以在代碼的更上一層統一處理錯誤。

tx, err := db.Begin()
err = tx.Exec(...)
err = tx.Commit()

tx := db.MustBegin()
tx.MustExec(...)
err = tx.Commit()

sqlx支持以上兩種開啟事務的方法。MustBegin返回sqlx.Tx,sqlx.Tx也提供了Select,Get之類的API,執行數據庫操作和使用sqlx.DB是一樣的。

以上代碼執行tx.MustExec(...)如果報錯的話,代碼將沒有機會運行到tx.Commit(),這樣數據庫連接會等到go進行垃圾回收的時候才能關閉,而且很高並發的話,可能會占滿數據庫連接數,造成站點無法訪問的情況。

tx := db.MustBegin()
defer tx.Rollback()
tx.MustExec(...)
err = tx.Commit()

代碼中加入defer tx.Rollback()就可以解決問題。通過前面的介紹已知defer是在方法即將結束時執行,哪怕是代碼出現異常也不會影響數據庫連接。

文章出處:基於gin的golang web開發:使用數據庫事務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM