3 ms·
String is a pointer/slice type under the hood, even if you don't see the asterisk. So when you are passing v, you are passing a reference to a slice which gets
by kortex 5y ago
String is a pointer/slice type under the hood, even if you don't see the asterisk. So when you are passing v, you are passing a reference to a slice which gets updated by the loop. Since the goroutines can run in parallel, you print whatever v is pointing to at the time.
C++ lambdas do the same thing if you pass a pointer.
Python would do the same thing if you had a mutable non-threadsafe objects passed to threads. Eg if you iterate over a list of dicts, and modify the dicts, you'll get the same effect.
So then the question becomes, why does v get re-used, instead of assigning a new pointer each time? Dunno, probably performance. I could see the latter generating a lot of garbage, which can be totally avoided if you don't pass mutable references to goroutines.
What go really lacks IMHO is some kind of const modifier for these kind of references. Maybe it does, all I remember are const scalars.
- jhgb 5y ago> String is a pointer/slice type under the hood, even if you don't see the asterisk. So when you are passing v, you are passing a reference to a slice which gets updated by the loop. Since the goroutines can run in parallel, you print whatever v is pointing to at the time. You'll have the same problem with a simple integer (for example, as in https://go.dev/play/p/uqvRoO3ynZt https://go.dev/play/p/uqvRoO3ynZt). Nothing to do with v being a reference to something.