Go's escape analysis and why my function return worked

by bonniesimonon 12/5/2025, 11:03 AMwith 72 comments

by tdfirthon 12/11/2025, 1:53 PM

I don’t think this is confusing to the vast majority of people writing Go.

In my experience, the average programmer isn’t even aware of the stack vs heap distinction these days. If you learned to write code in something like Python then coming at Go from “above” this will just work the way you expect.

If you come at Go from “below” then yeah it’s a bit weird.

by foldron 12/5/2025, 11:46 AM

This seems to be a persistent source of confusion. Escape analysis is just an optimization. You don't need to think about it to understand why your Go code behaves the way it does. Just imagine that everything is allocated on the heap and you won't have any surprises.

by jstanleyon 12/11/2025, 11:50 AM

It's not confusing that this works in Go. (In my opinion).

A straightforward reading of the code suggests that it should do what it does.

The confusion here is a property of C, not of Go. It's a property of C that you need to care about the difference between the stack and the heap, it's not a general fact about programming. I don't think Go is doing anything confusing.

by knorkeron 12/11/2025, 1:40 PM

Are you sure this is what's happening? Looks to me like the slice object is returned by value, and the array was always on the heap. See https://go.dev/play/p/Bez0BgRny7G (the address of the slice object changed, so it's not the same object on the heap)

Sure, Go has escape analysis, but is that really what's happening here?

Isn't this a better example of escape analysis: https://go.dev/play/p/qX4aWnnwQV2 (the object retains its address, always on the heap, in both caller and callee)

by nasretdinovon 12/11/2025, 9:50 AM

If the functions get inlined (which they might if they're small enough), then the code won't even need to allocate on heap! That's a kind of optimisation that's not really possible without transparent escape analysis.

by jasonthorsnesson 12/11/2025, 3:42 PM

You can run the compiler with a flag that shows all the escapes with -gcflags “-m” and there’s also support in goland and vscode to show the escapes as inline annotations in the editor. This sort of thing IMO is one of the useful things about IDEs: showing hints from later parts of the tool chain about how things are going to turn out

by samdoesnothingon 12/11/2025, 10:44 AM

Go is returning a copy of the slice, in the same way that C would return a copy of an int or struct if you returned it. The danger of C behaviour in this instance is that a stack allocated array decays into a pointer which points to the deallocated memory. Otherwise the behaviour is pretty similar between the languages.

by mwshermanon 12/11/2025, 3:22 PM

Shameless plug, if one wishes to track down allocations in Go, an allocations explorer for VS Code: https://marketplace.visualstudio.com/items?itemName=Clipperh...

by matthewaveryusaon 12/11/2025, 2:53 PM

Nope, this analysis is wrong. Decompile your code and look at what's going on: https://godbolt.org/z/f1nx9ffYK

The thing being returned is a slice (a fat pointer) that has pointer, length, capacity. In the code linked you'll see the fat pointer being returned from the function as values. in C you'd get just AX (the pointer, without length and cap)

    command-line-arguments_readLogsFromPartition_pc122:
            MOVQ    BX, AX     // slice.ptr   -> AX (first result register)
            MOVQ    SI, BX     // slice.len   -> BX (second)
            MOVQ    DX, CX     // slice.cap   -> CX (third)
The gargabe collection is happening in the FUNCDATA/PCDATA annotations, but I don't really know how that works.

by potato-peeleron 12/11/2025, 11:12 AM

If the variable was defined in the calling function itself, and a pointer was passed, I guess the variable will still be in the heap?

by metadaton 12/11/2025, 4:24 PM

Emojis in code comments make them unreadable. Why is this a thing?

by gethlyon 12/11/2025, 2:40 PM

> In C, you can't assign a value in a local function and then return it

I am so glad I never taken up C. This sound like a nightmare of a DX to me.