上下文包与完成通道以避免 goroutine 泄漏

mof*_*ury 8 concurrency go

有两种不同的方法来清理 goroutine。

  1. 使用kill 通道来发出取消信号,并使用done 通道来指示goroutine 已终止。

    type Worker struct {
      Done chan struct{}
      Kill chan struct{}
      Jobs chan Job
    }
    
    func (w *Worker) Run() {
      defer func() {
        w.Done <- struct{}{}
      }
      for {
        select {
        case <-w.Kill:
          return
        case j := <-w.Jobs:
          // Do some work
      }
    }
    
    go w.Run()
    w.Kill <- struct{}{}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 用于context取消

    type Worker struct {
      Ctx context.Context
      Cancel context.CancelFunc
      Jobs chan Job
    }
    
    func (w *Worker) Run() {
      for {
        select {
        case <-w.Ctx.Done():
          return
        case j := <-w.Jobs:
          // Do some work
      }
    }
    
    go w.Run()
    w.Cancel()
    
    Run Code Online (Sandbox Code Playgroud)

每种方法的优点/缺点是什么?我应该默认哪一个?

我知道,如果我想杀死一棵互连的 goroutine 树,我应该使用上下文方法,但我们只是说我有一个简单的工作程序,它不会在内部启动其他 goroutine。

pet*_*rSO 0

\n

Go 1.7 发行说明

\n\n

语境

\n\n

Go 1.7 将 golang.org/x/net/context 包作为上下文移动到标准库中。这允许使用上下文进行取消、超时以及在其他标准库包(包括 net、net/http 和 os/exec)中传递请求范围的数据,如下所述。

\n\n

有关上下文的更多信息,请参阅包\n 文档和 Go 博客文章 \xe2\x80\x9c Go 并发模式:\n 上下文.\xe2\x80\x9d

\n
\n\n
\n\n

有问题。引入 context 包来解决这些问题。

\n\n

现在您已经阅读了所有相关文档,您的问题是什么?

\n

  • 太棒了,我不确定取消 goroutine 的最新规范方法是什么,因为我认为我看到了一篇误导性的文章,并且认为有些人认为上下文不适合取消。根据您的回答,我认为它进一步证实了上下文应该是取消的默认首选方法。 (2认同)