5 ms·
Or pass it into the func, especially if its running in a goroutine. for _, ele := range eles { go func(ele string) { // use ele }(ele) }
by anonfunction 9y ago
Or pass it into the func, especially if its running in a goroutine.
for _, ele := range eles { go func(ele string) { // use ele }(ele) }
- roskilli 9y agoAlso the other "fun" approach: for _, elem := range elems { elem := elem; go func() { /* use elem */ }() }
- frou_dh 9y agoIt's a shame to have code end up like this when Go is supposed to be anti- "stutter".
- innagadadavida 9y agoThis might have been done by Go for perf reasons. Why should the Go compiler copy a new variable on the stack every loop iteration?
- Merovius 9y agoNo, not really, it's a natural and unintended consequence of how the spec scopes variables in loops/switches/conditionals: https://golang.org/ref/spec#Blocks https://golang.org/ref/spec#Blocks The problem you are trying to solve is, that with a statement like for i := 0; i < n; i++ { doAThing(i) } you want `i` to be valid inside the loop body, in the for-clauses but not outside the for-statement. Go solves this by saying that an if/for/switch statement has an implicit block surrounding them and that block is what scopes the loop variables. AFAIK no one considered, that this would have this consequence in relation to closures. Performance wouldn't really matter, because compilers tend to be pretty good at optimizing these kinds of things. They already reorder when they check for the condition and how they jump non-intuitively and the naive instruction sequence would involve freeing some stack-space at the end of the loop, reallocating it in the next iteration and then writing the new value to it. Figuring out that you can save the actual stack-pointer operations isn't that hard.
- innagadadavida 9y agoCan the compiler implicitly copy i, basically convert it to: for i := 0; i < n; i++ { i := i doAThing(i) }
- Merovius 9y agoSure. It's an easy problem to fix, now that the team is aware it. I'm pretty sure they'll solve it for Go 2. In the meantime, it would break the compatibility promise, so it's just a kludge we have to live with. I basically just wanted to point out that the problem isn't so much an implementation question (or about performance). But that no one thought of it and it's now mainly a question of how to best phrase the spec for this :)