Stack and heap

Memory is arranged into two main areas – stack and heap. There is a stack for the application entry point function (main), and additional stacks are created with each goroutine, which are stored in the heap. The stack is, as its name suggests, a memory portion that grows with each function call, and shrinks when the function returns. The heap is made of a series of regions of memory that are dynamically allocated, and their lifetime is not defined a priori as the items in the stack; heap space can be allocated and freed at any time. 

All the variables that outlive the function where they are defined are stored in the heap, such as a returned pointer. The compiler uses a process called escape analysis to check which variables go on the heap. This can be verified with the go tool compile -m command.

Variables in the stack come and go with the function's execution. Let's take a look at a practical example of how the stack works:

func main() {
var a, b = 0, 1
f1(a,b)
f2(a)
}

func f1(a, b int) {
c := a + b
f2(c)
}

func f2(c int) {
print(c)
}

We have the main function calling a function called f1, which calls another function called f2. Then, the same function is called directly by main.

When the main function starts, the stack grows with the variables that are being used. In memory, this would look something like the following table, where each column represents the pseudo state of the stack, which it represents how the stack changes in time, going from left to right:

main invoked f1 invoked f2 invoked f2 return f1 returns f2 invoked f2 returns main returns
main() main() main() main() main() main() main() // empty
a = 0 a = 0 a = 0 a = 0 a = 0 a = 0 a = 0
b = 1 b = 1 b = 1 b = 1 b = 1 b = 1 b = 1
f1() f1() f1() f2()
a = 0 a = 0 a = 0 c = 0
b = 1 b = 1 b = 1
c = 1 c = 1 c = 1
f2()
c = 1

When f1 gets called, the stack grows again by copying the a and b variables in the new part and adding the new variable, c. The same thing happens for f2. When f2 returns, the stack shrinks by getting rid of the function and its variables, which is what happens when f1 finishes. When f2 is called directly, it grows again by recycling the same memory part that was used for f1.

The garbage collector is responsible for cleaning up the unreferenced values in the heap, so avoiding storing data in it is a good way of lowering the work of the garbage collector (GC), which causes a slight decrease in performance in the app when the GC is running. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.214.155