簡體   English   中英

使用 errgroup 終止阻塞 goroutine

[英]terminating blocking goroutines with errgroup

我有兩個任務在 go 例程中運行。 我正在使用錯誤組。 我不確定如何正確使用 errgroup.WithContext。

在下面的代碼中,task1 正在返回錯誤,我想在發生這種情況時終止 task2(長時間運行)。 請注意,在此示例中添加 time.sleep 只是為了模擬我的問題。 實際上 task1 和 task2 正在做真正的工作並且沒有任何睡眠呼叫。

package main

import (
    "context"
    "fmt"
    "golang.org/x/sync/errgroup"
    "time"
)

func task1(ctx context.Context) error {
    time.Sleep(5 * time.Second)
    fmt.Println("first finished, pretend error happened")
    return ctx.Err()
}

func task2(ctx context.Context) error {
    select {
    case <-ctx.Done():
        fmt.Println("task 1 is finished with error")
        return ctx.Err()
    default:
        fmt.Println("second started")
        time.Sleep(50 * time.Second)
        fmt.Println("second finished")
    }
    return nil
}

func test() (err error) {
    ctx := context.Background()
    g, gctx := errgroup.WithContext(ctx)

    g.Go(func() error {
        return task1(gctx)
    })

    g.Go(func() error {
        return task2(gctx)
    })

    err = g.Wait()
    if err != nil {
        fmt.Println("wait done")
    }

    return err
}

func main() {
    fmt.Println("main")
    err := test()
    if err != nil {
        fmt.Println("main err")
        fmt.Println(err.Error())
    }
}


正確處理上下文取消而不是時間取決於您的任務。在time.Sleep中睡覺。

如 errgroup 文檔中所述:

WithContext 返回一個新組和一個從 ctx 派生的關聯上下文。

派生的上下文在第一次傳遞給 Go 的 function 返回非零錯誤或第一次 Wait 返回時被取消,以先發生者為准。

您正在使用錯誤組,但您的上下文處理需要重構。

這是您的任務 2 的重構:

func task2(ctx context.Context) error {
    errCh := make(chan bool)

    go func() {
        time.Sleep(50 * time.Second)
        errCh <- true
    }()

    select {
    case <-ctx.Done():
        return fmt.Errorf("context done: %w", ctx.Err())
    case <-errCh:
        return errors.New("task 2 failed")
    }
}

使用這樣的 select,您等待第一個通道發射。 在這種情況下,它是上下文過期,除非您將 time sleep 修改為更低。 示例游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM