Variable Capture and Loops
The difference, it turns out, has to do with how variables are bound in loops, and how values are captured in anonymous functions. The Swift (and Objective-C) behavior – which I was most used to at the time of writing – was to bind
i
as a different immutable value in each loop iteration, then capture a reference to that value each time through.Go, on the other hand, binds a single mutable value for the entire loop, then captures a reference to that single variable instead, only getting the value in question at the time the function is executed.
[…]
Interestingly enough, we can even “introduce” this bug in Swift code by using a C-like loop instead of the nicer
for
–in
syntax[…] Since this style explicitly uses a single mutablei
for the entire loop, rather than binding a newi
for each iteration, the “buggy” behavior – printing five sixes – occurs. Swift is even kind enough to make the mutability ofi
here more explicit, by requiring it be annotatedvar
in the loop declaration.
See also: Capturing references in closures, Capture Lists, The __block Storage Type.