Re:Down the Golang Nil Rabbit Hole
by throwaway894345 on Tuesday March 30, 2021 @01:48PM
(#26637835)
That makes sense, so most likely Go's compiler is promoting the new variable to the heap (I doubt it's smart enough to recognize that the new `v` is only used by the closure which in turn is only used by the new goroutine and thus safe to allocate `v` in the new goroutine's stack). In any case, thanks for the link, I didn't know there was a formal name for the problem.
[ Parent
| on HN ]
So again: Allocations of regions of memory representing values, not variables, are what does or does not get promoted. If `values` is an array of strings, do you think the following makes a new string on the heap (that is, a new 16 byte heap allocation, internally pointing to the same variable-sized region of memory)?
for _, v := range values {
go func(v string) {
fmt.Println(v)
done <- true
}(v)
}
No, the 16 bytes will be copied onto the goroutine's stack.Do you think it's smart enough to do the trivial transformation of the first into the second?
Re:Down the Golang Nil Rabbit Hole
by throwaway894345 on Tuesday March 30, 2021 @05:39PM
(#26640895)
> So again: Allocations of regions of memory representing values, not variables, are what does or does not get promoted.
Right, I understand the difference between a variable and a region of memory.
> If `values` is an array of strings, do you think the following makes a new string on the heap (that is, a new 16 byte heap allocation, internally pointing to the same variable-sized region of memory)?
No.
> Do you think it's smart enough to do the trivial transformation of the first into the second?
I guess I'm surprised that the semantics for the `v := v` in a loop thing are "this will get allocated somewhere else such that it's guaranteed not to be stomped on by another loop iteration". For example:
for _, v := range []int{2, 4, 6} {
v := v
mut := sync.Mutex{}
go func() {
mut.Lock()
fmt.Println(v)
mut.Unlock()
done <- true
}()
go func() {
mut.Lock()
v = 1
mut.Unlock()
done <- true
}()
}
If it allocates `v` on the goroutines' stacks, then it won't catch the mutation, so presumably it allocates on the heap at least in that case. In whatever case, the semantics are surprising to me.