传递上下文的最佳方法.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)
  }
}

两者都可以。要记住的关键是上下文是不可变的。这意味着没有其他一些Goroutine在尝试阅读上下文的风险,因此您不必担心正常的同步方法。

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


术语注释:您的原始问题(我为清晰而编辑)询问了执行"封闭中的goroutine"。从技术上讲,这是无意的。但这是一个普遍的混乱。Goroutines是执行的轻重量螺纹。功能是代码的位。它们不是同一件事,因此将功能或封闭性称为Goroutines并没有真正的意义。有关更多详细信息,请参见此答案。

tl; dr;除非您使用value构建异常大的上下文,否则在任何一种情况下都不会产生很大的不同。

示例1)称为GO例程的匿名函数不是封闭的,因为您同时通过i和ctx作为参数(按照定义,封闭,包含外部变量或状态而无需将它们传递给参数)

示例2)称为GO例程的匿名函数是封闭式的,因为它使用了" run()"外部函数中的变量。不将它们传递给参数/参数

传递非点数参数使变量的副本不通过内部更改来修改原始(外部)。使用闭合可以通过内部编辑更改外部变量(状态)。上下文是不可变的,因此无论是使用封闭还是将它们作为参数传递给它们,就可变性而言无关紧要。不同之处在于,您是否将由于传递作为参数/参数而复制上下文变量的附加处理。

最新更新