Go func closure in loop

closures, concurrency, go

Solution

Because the first one gets a copy of the loop counter each time. Whereas the second gets the variable captured as part of a closure.

In the first, you're passing it in here in every iteration of the loop:

go func(j int) {
    defer wg.Done()

    fmt.Println(j)
}(i) // <------------ its passed in here as part of each loop iteration

The second one receives nothing.. so, the loop counter `i` is captured as part of a closure. By the time the first go routine executes, the `for` loop has finished. The loop finishing has set the `i` variable (that is now part of a closure) to 10. Go routine #1 executes and prints the value of `i`.. which is now already 10 and the rest follow suit.

TLDR: The problem here is that the loop is finishing before any go routines are scheduled to be run - its just that quick. Therefore, `i == 10` when the go routines run.

Problem

When executing the following code I get what I expect when the first loop is done (sequence from 0 to 9). But when the second loop finishes, the result is not what I expected (I expected the same result as in the first loop, but it prints only '10's): ``` package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func(j int) { defer wg.Done() fmt.Println(j) }(i) } wg.Wait() fmt.Println("done first") for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() fmt.Println(i) }() } wg.Wait() fmt.Println("done second") } ``` Output: ``` 0 1 2 3 4 5 6 7 8 9 done first 10 10 10 10 10 10 10 10 10 10 done second ``` Why doesn't the second loop print a sequence?

Original source

Related problems