如何在多個goroutine中正確關閉共享的數據庫連接?

如何在多個goroutine中正確關閉共享的數據庫連接?

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

在Go語言并發編程中,多個goroutine共享數據庫連接是常見場景。不當的連接關閉處理可能導致資源泄漏或其他問題。本文將分析問題并提供解決方案。

問題分析:

直接在主goroutine中使用defer db.Close()無法保證所有goroutine執行完畢后再關閉連接,因為主goroutine可能在子goroutine執行前就已結束。將db.Close()放在每個querydb函數中也不可行,因為這會導致多個goroutine競爭關閉同一個連接,引發錯誤。

解決方案:

使用WaitGroup同步goroutine的執行,確保所有goroutine完成任務后再關閉連接。

改進后的代碼示例:

package main  import (     "fmt"     "sync"     "time" )  // 模擬數據庫連接 type dbConn struct{}  func (c *dbConn) Close() error {     fmt.Println("Closing database connection...")     return nil }  func openDb() *dbConn {     fmt.Println("Opening database connection...")     return &dbConn{} }  func querydb(db *dbConn, i int, wg *sync.WaitGroup) {     defer wg.Done()     fmt.Printf("Goroutine %d querying database...n", i)     time.Sleep(time.Second) // 模擬查詢操作 }  func main() {     db := openDb()     var wg sync.WaitGroup     for i := 0; i < 5; i++ {         wg.Add(1)         go querydb(db, i, &wg)     }     wg.Wait() // 等待所有goroutine完成     err := db.Close()     if err != nil {         fmt.Printf("Error closing database connection: %vn", err)     } } 

代碼解釋:

  1. 引入sync.WaitGroup用于同步goroutine。
  2. wg.Add(1)在啟動每個goroutine前增加計數器。
  3. defer wg.Done()在每個goroutine結束后減少計數器。
  4. wg.Wait()阻塞主goroutine,直到所有計數器歸零,即所有goroutine執行完畢。
  5. 最后,安全地關閉數據庫連接。

此方法有效地解決了共享數據庫連接的關閉問題,保證了資源的正確釋放,避免了資源泄漏和并發錯誤。 其他方法,例如使用context包,也可以實現類似功能,但WaitGroup在此場景下更為簡潔直接。

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