慣用的Goroutine 終止和錯誤處理:案例研究
在Go 中,處理Goroutine 終止對於開發人員來說通常是一個挑戰。一個常見的問題是確保發生錯誤時正確清理 goroutine。本文示範了使用錯誤分組來解決此問題的優雅且慣用的解決方案。
考慮以下範例:
package main import ( "sync" "time" ) func fetchAll() error { wg := sync.WaitGroup{} errs := make(chan error) // run all the http requests in parallel for i := 0; i < 4; i++ { wg.Add(1) go func(i int) { defer wg.Done() // pretend this does an http request and returns an error time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) errs <- fmt.Errorf("goroutine %d's error returned", i) }(i) } // wait until all the fetches are done and close the error // channel so the loop below terminates go func() { wg.Wait() close(errs) }() // return the first error for err := range errs { if err != nil { return err } } return nil }
此實作有一個嚴重缺陷:它洩漏了 goroutine。修復方法是使用錯誤群組:
package main import ( "context" "fmt" "math/rand" "time" "golang.org/x/sync/errgroup" ) func fetchAll(ctx context.Context) error { errs, ctx := errgroup.WithContext(ctx) // run all the http requests in parallel for i := 0; i < 4; i++ { errs.Go(func() error { // pretend this does an http request and returns an error time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) return fmt.Errorf("error in go routine, bailing") }) } // Wait for completion and return the first error (if any) return errs.Wait() }
錯誤群組會自動等待所有 goroutine 成功完成,或在發生錯誤時取消剩餘的 goroutine。在上述情況下,遇到錯誤的第一個 goroutine 會觸發所有其他 goroutine 的取消,並將錯誤傳回呼叫者。當周圍的上下文被取消時,上下文的使用確保了優雅的終止。
以上是如何優雅地終止 Go 中的 Goroutines 並處理錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!