首页 > 解决方案 > 将 context.Context 传递给在单独的 goroutine 中执行的闭包的最佳方法

问题描述

传递context.Context给闭包以在单独的 goroutine 中执行的最佳方法是什么?

由于我没有context.Context在闭包内发生变异,我假设这两个选项都是有效的。第二个选项可以通过不复制界面为我节省一点点内存。

1) 作为参数传递

func run(ctx context.Context) {
  for i := 0; i <= 5; i++ {
    go func(id int, ictx context.Context) {
      for {
        select {
          case <- ictx.Done():
            return
          default:
            // do something
        }
      }
    }(i, ctx)
  }
}

2) 暴露外部上下文变量

func run(ctx context.Context) {
  for i := 0; i <= 5; i++ {
    go func(id int) {
      for {
        select {
          case <- ctx.Done():
            return
          default:
            // do something
        }
      }
    }(i)
  }
}

标签: goclosuresgoroutine

解决方案


两者都应该没问题。要记住的关键是上下文是不可变的。这意味着没有竞争条件的风险,即在您尝试读取上下文时,其他一些 goroutine 正在更新上下文,因此您无需担心正常的同步方法。

所以简而言之,不需要什么特别的,所以#2就可以了。由于 #1 实际上并没有执行闭包,因此在您想要执行一个命名函数的情况下它是理想的,它需要一个上下文参数


关于术语的注意事项:您最初的问题(为了清楚起见,我对其进行了编辑)询问了有关执行“闭包中的 goroutine”的问题。从技术上讲,这是无稽之谈。但这是一个常见的混淆。Goroutines 是轻量级的执行线程。函数是一些代码。它们不是一回事,因此将函数或闭包称为 goroutines 并没有真正的意义。有关更多详细信息,请参阅此答案


推荐阅读