Stack vs heap allocation of structs in Go, and how they relate to garbage collection

I’m new to Go and I’m experiencing a bit of cognitive dissonance between C-style stack-based programming where automatic variables live on the stack and allocated memory lives on the heap and Python-style stack-based-programming where the only thing that lives on the stack are references/pointers to objects on the heap.

As far as I can tell, the two following functions give the same output:

func myFunction() (*MyStructType, error) {
    var chunk *MyStructType = new(HeaderChunk)

    ...

    return chunk, nil
}


func myFunction() (*MyStructType, error) {
    var chunk MyStructType

    ...

    return &chunk, nil
}

i.e., allocate a new struct and return it.

If I’d written that in C, the first one would have put an object on the heap and the second would have put it on the stack. The first would return a pointer to the heap, the second would return a pointer to the stack, which would have evaporated by the time the function had returned, which would be a Bad Thing.

If I’d written it in Python (or many other modern languages except C#) example 2 would not have been possible.

I get that Go garbage collects both values, so both of the above forms are fine.

To quote:

Note that, unlike in C, it’s perfectly OK to return the address of a
local variable; the storage associated with the variable survives
after the function returns. In fact, taking the address of a composite
literal allocates a fresh instance each time it is evaluated, so we
can combine these last two lines.

http://golang.org/doc/effective_go.html#functions

But it raises a couple of questions.

  1. In example 1, the struct is declared on the heap. What about example 2? Is that declared on the stack in the same way it would be in C or does it go on the heap too?

  2. If example 2 is declared on the stack, how does it stay available after the function returns?

  3. If example 2 is actually declared on the heap, how is it that structs are passed by value rather than by reference? What’s the point of pointers in this case?

5 Answers
5

Leave a Comment