将context.Context传递给在单独的goroutine中执行的闭包的最佳方法

What is best way to pass context.Context to closure to be executed in a separate goroutine?

Since I'm not mutating context.Context inside the closure, I assume both options are valid. 2nd option can save me tiny bit of memory by not copying the interface.

1) pass as an argument

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) expose outer context variable

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)
  }
}

Both should be fine. The key to remember is that contexts are immutable. This means there's no risk of a race condition where some other goroutine is updating the context as you're trying to read it, so you don't need to worry about the normal synchronization methods.

So in short, nothing special is needed so #2 is just fine. Since #1 isn't actually executing a closure, it's ideal in situations where you want to execute a named function, which takes a context argument


Note on terminology: Your original question (which I edited for clarity) asked about executing "a goroutine in a closure." Technically speaking, this is non-sense. But it's a common confusion. Goroutines are light-weight threads of execution. Functions are bits of code. They are not the same thing, so referring to functions or closures as goroutines doesn't really make sense. See this answer for more details.