在Go語言中,如何正確關閉多個Goroutine共享的數據庫連接?

在Go語言中,如何正確關閉多個Goroutine共享的數據庫連接?

go語言多Goroutine共享數據庫連接的優雅關閉

在Go語言并發編程中,多個Goroutine共享數據庫連接時,如何安全地關閉連接是一個關鍵問題。不當的關閉方式可能導致數據丟失或程序崩潰。本文將探討幾種方案,并分析其優缺點。

假設我們有一個場景:多個Goroutine并發執行數據庫查詢操作,共享同一個數據庫連接。

錯誤示范:使用defer在主Goroutine關閉連接

以下代碼演示了一個常見的錯誤:

立即學習go語言免費學習筆記(深入)”;

db := openDB() defer db.Close() // 錯誤:在主Goroutine關閉,其他Goroutine可能仍在使用  for i := 0; i < 10; i++ {     go func(i int) {         queryDB(db, i)     }(i) } // ... 其他代碼 ...

defer db.Close() 會在主Goroutine結束時執行,但此時其他Goroutine可能仍在使用數據庫連接,導致程序崩潰或數據錯誤。

錯誤示范:在每個Goroutine中關閉連接

將db.Close()放在每個Goroutine中也不是正確的方案:

func queryDB(db *DB, i int) {     defer db.Close() // 錯誤:每個Goroutine都嘗試關閉連接     // ... 數據庫查詢操作 ... }

這會導致連接被多次關閉,引發錯誤。

正確方案一:使用WaitGroup同步Goroutine

使用sync.WaitGroup可以確保所有Goroutine都完成工作后再關閉連接:

var wg sync.WaitGroup db := openDB() defer db.Close() // 正確:在所有Goroutine完成后關閉  for i := 0; i < 10; i++ {     wg.Add(1)     go func(i int) {         defer wg.Done()         queryDB(db, i)     }(i) } wg.Wait() // 等待所有Goroutine完成

此方法通過wg.Add(1)和wg.Done()來計數Goroutine,wg.Wait()阻塞直到所有Goroutine完成,確保連接在安全的時間點關閉。

正確方案二:使用全局變量和主Goroutine控制

另一種更簡潔的方法是將數據庫連接定義為全局變量,并在主Goroutine中統一管理:

var db *DB  func main() {     db = openDB()     defer db.Close() // 正確:在主Goroutine統一關閉      // ... 啟動Goroutine ... }  func queryDB(i int) {     // ... 數據庫查詢操作 ... }

這種方式清晰地將連接的管理集中在主Goroutine,避免了并發訪問和關閉的問題。

選擇哪種方案取決于具體應用場景和代碼復雜度。WaitGroup方法適用于更復雜的并發場景,而全局變量方法在簡單場景下更簡潔易懂。 關鍵在于確保數據庫連接只被關閉一次,并且在所有Goroutine完成操作之后關閉。

? 版權聲明
THE END
喜歡就支持一下吧
點贊6 分享