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) } }
代碼解釋:
- 引入sync.WaitGroup用于同步goroutine。
- wg.Add(1)在啟動每個goroutine前增加計數器。
- defer wg.Done()在每個goroutine結束后減少計數器。
- wg.Wait()阻塞主goroutine,直到所有計數器歸零,即所有goroutine執行完畢。
- 最后,安全地關閉數據庫連接。
此方法有效地解決了共享數據庫連接的關閉問題,保證了資源的正確釋放,避免了資源泄漏和并發錯誤。 其他方法,例如使用context包,也可以實現類似功能,但WaitGroup在此場景下更為簡潔直接。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END