簡體   English   中英

如何處理關閉同一頻道的多個 go-routines?

[英]How to handle multiple go-routines closing the same channel?

我有 2 個從單個頻道讀取的 go-routines。 4 秒后,我取消上下文並終止 select 循環。 在終止循環之前,我在通道上調用了 close,因為有 2 個 go-routine,close 被調用了兩次並導致恐慌,因為其中一個 go-routine 已經關閉了通道。 目前我正在使用恢復從恐慌中恢復,有沒有更好的方法來做到這一點?

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func numberGen(ctx context.Context, numChan chan int) {
    num := 0
    doneCh := ctx.Done()
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recovered from ", r)
        }
    }()
    for {
        select {
        case <-doneCh:
            fmt.Println("done generating...")
            close(numChan)
            return
        default:
            num++
            numChan <- num
        }
    }
}

func main() {
    ctx, cancelFn := context.WithCancel(context.Background())
    numChan := make(chan int)
    var wg sync.WaitGroup
    wg.Add(2)
    go numberGen(ctx, numChan)
    go numberGen(ctx, numChan)

    go func(cfn context.CancelFunc) {
        time.Sleep(10 * time.Millisecond)
        cfn()
    }(cancelFn)

    for n := range numChan {
        fmt.Println("received value ", n)
    }

    time.Sleep(2 * time.Second)
}

在 goroutine 完成發送值后關閉通道。

var wg sync.WaitGroup
wg.Add(2)
go numberGen(ctx, numChan, &wg)
go numberGen(ctx, numChan, &wg)

go func() {
    wg.Wait()
    close(numChan)
}()

更新numberGen以在等待組上調用Done() 另外,刪除對close的調用。

func numberGen(ctx context.Context, numChan chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    ...

暫無
暫無

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

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