https://golang.org/doc/faq#stack_or_heap
stack and pointers
我不能解释地像 William Kennedy一样优秀,那就让我来做一个汇总.
一个变量可以被分配在 heap
或是stack
:
- The stack contains the ongoing variables for a given goroutine. Once a function returned, the variables are popped from the stack.
- The heap contains the shared variables (global variables, etc.), and anything on the heap is maaged by the Garbage Collector.
简而言之,当你需要Sharing
变量,可以使用指针;
- 如果你需要(
passing pointers
orpassing referencs
) (sharing down),变量定义通常在stack
内 - 如果你需要(
returning pointers
orreturning references
)(sharing up),变量定义通常在heap
内
注: 指针变量像其他的变量一样并不特殊,它们有一个内存分配而且它们保存一个值, 不论值的类型它们均可以指向,通常也占用相同的内存大小。
注: The stack is important because it provides the physical memory space for the frame boundaries that are given to each individual function.
注: All stack memory below the active frame is invalid but memory from the active frame and above is valid.
注: It’s during each function call, when the frame is taken, that the stack memory for that frame is wiped clean.
注: Making a function call means the goroutine needs to frame a new section of memory on the stack.
From the FAQ
https://golang.org/doc/faq#stack_or_heap
When possible, the Go compilers will allocate variables that are local to a function in that function’s stack frame.
However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors.
结论
Pointers serve one purpose, to share a value with a function so the function can read and write to that value even though the value does not exist directly inside its own frame.
Each semantic comes with a benefit and cost. Value semantics keep values on the stack which reduces pressure on the GC. However, there are different copies of any given value that must be stored, tracked and maintained. Pointer semantics place values on the heap which can put pressure on the GC. However, they are efficient because there is only one value that needs to be stored, tracked and maintained. The key is using each semantic correctly, consistently and in balance.
Ask the compiler
Compiler flags
- go help build
- go tool compile -h
- go build -gcflags “-m”
When are values construcated on the heap?
When a value could possibly be referenced after the function that constructed the value returns.
When the compiler determines a value is too large to fit on the stack.
When the compiler doesn’t know the size of a value at compile time.
Points to remember
Optimize for correctness, not performance.
Go only puts function variables on the stack if it can prove a variable is not used after the function returns.
Sharing down typically stays on the stack.
Sharing up typically escapes to the heap.
Ask the compiler to find out.
Don’t guess. Use the tooling.