首页 > 解决方案 > 上下文包与完成通道以避免 goroutine 泄漏

问题描述

清理 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{}{}
    
  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()
    

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

我知道如果我想杀死一棵相互连接的 goroutines 树,我应该使用上下文方法,但假设我有一个简单的 worker,它不会在内部启动其他 goroutines。

标签: goconcurrency

解决方案


Go 1.7 发行说明

语境

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

有关上下文的更多信息,请参阅包文档和 Go 博客文章“<a href="https://blog.golang.org/context" rel="nofollow noreferrer">Go 并发模式:上下文。”</p >


有问题。引入了上下文包来解决它们。

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


推荐阅读