The notion of stack vs heap allocation isn't something that even exists in the language. Users are expected to not worry about it... until, of course, until you're optimizing performance and you need to worry about it.
This is one of the best and worst aspects with Go. Anyone can write pretty performant code without having to understand the underlying memory model. If you get to the point where you are trying to optimize at this level, the benefits of using a more approachable language start to fall apart and you spend more time chasing implementation details. t.Buf = []byte{}
you can just do: t.Buf = nil
Either that or the escape analysis just isn't smart enough; taking a pointer to an internal component of an interface value seems like a bit of a stretch.
It almost doesn't use unsafe except one line to cast pointer types. I measured practical performance boost with "container/list" implementation hooked to my allocator. All in all it performs 2-5 times faster or up to 10 times faster if we can get rid[2] of any and allocations implied by the use of it.
All in all, heap allocations can be not that bad at all if you approach them from another angle.
returningfory2•2mo ago
Here's an example, I think: suppose the method spawns a new goroutine that contains a reference to `chunkStore`. This goroutine can outlive the `ReadBytes` function call, and thus Go has to heap allocate the thing being referenced.
In general, this kind of example makes me suspect that Go's escape analysis algorithm treats any method call as a black box and heap allocates anything being passed to it by reference.