首頁  >  文章  >  後端開發  >  如何優雅地終止 Go 中的 Goroutines 並處理錯誤?

如何優雅地終止 Go 中的 Goroutines 並處理錯誤?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-11-12 07:21:02887瀏覽

How to Gracefully Terminate Goroutines and Handle Errors in Go?

慣用的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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn