Hacker News new | ask | show | jobs
by masklinn 1603 days ago
The "trap" of the snippet is that `cp` is an array of pointers.

What it shows is that Go doesn't have a `value` per iteration, it has a single `value` for the entire loop which it updates for each iteration. This means if you store a pointer to that, you're going to store a pointer to the loop variable which gets updated, and thus at the end of the loop you'll have stored a bunch of pointers to the last item.

This is most commonly an issue when creating a closure inside a loop, as the closure closes over the binding, and since Go has a single binding for the entire loop all the closures will get the same value.

1 comments

This has suprised me twice, once in my own code where i ended up ot really understand the problem but just mutated the code till it worked and then later when I was helping someone with their code and the way they structured the question made the still suprising answer memorable.

A fix wouldn't be unwelcome but it seems it would have a good chance to cause performance regression - a lot more allocated values maybe on a lot of inner loops. I guess escape analysis might help avoid the allovations in the general case. ?

> A fix wouldn't be unwelcome but it seems it would have a good chance to cause performance regression - a lot more allocated values maybe on a lot of inner loops. I guess escape analysis might help avoid the allovations in the general case. ?

It seems unlikely unless the code is already incorrect (aka you're closing over or otherwise leaking the iteration variable).

But regardless of how I dislike the current loop's scoping this is a significant semantics change so it would obviously have to be opt-in (and it would hopefully come alongside making range loops less crummy e.g. with an actual iterator interface).