Question

Why does this:

for i := 0; i < 3; i++ {
    go func(i int) {
        fmt.Printf("%d", i)
    }(i)
}

prints 012

while this:

for i := 0; i < 3; i++ {
    go func() {
        fmt.Printf("%d", i)
    }()
}

prints 333?

Was it helpful?

Solution

While goroutines are cheap, they aren't free. There is some, but little, overhead in creating them.

In your first program, the value of i is preserved into the goroutines because you're passing it in as an argument. (Each goroutine gets its own copy of i's value at that moment.)

In your second program, the value of i is already 3 before the first goroutine has started. Remember that goroutines share the same memory space in a Go program, so in this case, each goroutine is looking at the same i when it prints it out.

OTHER TIPS

Adding a print statement just after your for loop should makes things clear for you. You’ll see that that print statement runs before your goroutine function.

When all you do in a for loop is to launch a new goroutine, your loop passes very fast and usually finishes even before your first goroutine starts. So when your goroutines start your loop is already finished and the value of if i is 3. Keep that in mind.

When you pass the i as a function argument, like you do in your first example, it’s current value is copied to the function stack, so the functions receives its current value as an argument. That’s why you’ll see 012. But when a closure function just uses a variable in its surrounding scope, like you do in your second example, it accesses its current value when it is run, which in your case is after the loop has finished and i has reached 3.

You can see this effect with this code:

for i := 0; i < 3; i++ {
    go func(arg int) {
        fmt.Printf("%d %d\n", arg, i)
    }(i)
}

which produces this output:

0 3
1 3
2 3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top