Stack vs heap allocation with pointers in Go
Jul 23, 2025 am 04:14 AMStack allocation is suitable for small local variables with clear life cycles, and is automatically managed, with fast speed but many restrictions; heap allocation is used for data with long or uncertain life cycles, and is flexible but has a performance cost. The Go compiler automatically determines the variable allocation position through escape analysis, and if the variable may escape from the current function scope, it will be allocated to the heap. Common situations that cause escape include: returning local variable pointers, assigning values to interface types, and passing in goroutines. The escape analysis results can be viewed through -gcflags="-m". When using pointers, you should pay attention to the variable life cycle to avoid unnecessary escapes.
In Go, understanding the memory allocation mechanism of stack and heap is very important for writing efficient and safe code, especially when pointers are involved. Simply put, the stack is used to store small local variables with a clear life cycle, while the heap is used for data that requires longer survival or is of uncertain size .

Go's compiler automatically decides whether variables are allocated on the stack or on the heap, but this decision can be affected in some ways, especially when using pointers.
Stack allocation: Fast and automatic management
Stack allocation is the default behavior and applies to local variables created inside functions, especially those that will not be returned or escaped to other goroutines.

- Fast speed : Because the stack memory is continuous, allocation and release are very efficient.
- Automatic cleaning : After the function call is finished, the variables on the stack will be automatically destroyed.
- Many restrictions : You cannot pass a pointer to a stack variable to an external function or return, otherwise it will cause a dangling pointer.
For example:
func example() *int { x := 10 return &x // Warning: Return the address of the local variable, x will be transferred to the heap}
Although you are writing stack variables, the Go compiler detects "escape" behavior and automatically assigns it to the heap to avoid errors.

Heap allocation: flexible but overhead
Heap memory is managed by a garbage collector (GC) and is suitable for objects with long or uncertain life cycles.
- Manual application, automatic recycling : Objects created using
new
ormake
will be placed on the heap. - Performance cost : Compared to stacks, heap allocation is slower and increases GC pressure.
- Applicable scenarios : Objects need to be used across functions, as return values, or have a large amount of data.
for example:
func createValue() *int { x := new(int) // explicitly allocated on the heap *x = 20 Return x }
The returned pointer here points to the variable in the heap and will not be destroyed as the function ends.
Pointer and Escape Analysis: Key Roles of the Go Compiler
The Go compiler will perform escape analysis during the compilation stage to determine whether a variable may "escape" out of the scope of the current function. If so, it will be automatically allocated to the heap.
Common situations that cause variable escape include:
- Returns a pointer to a local variable
- Assign variables to interface types (such as
interface{}
) - Pass the variable to goroutine (because concurrent access is possible)
You can view the escape analysis results through -gcflags="-m"
:
go build -gcflags="-m" main.go
The output may display information like this:
main.go:10:5: moved to heap: x
This means that the variable x is allocated to the heap.
Practical advice: Let the compiler make decisions, but stay conscious
- Don't deliberately pursue "variables must be on the stack" unless you are optimizing hot code.
- Pay attention to the life cycle of the variable when using pointers to avoid unnecessary escapes.
- Use the escape analysis tool to see what actually happens in your code.
For example, in the following code:
func foo() { s := "hello" fmt.Println(&s) }
s
is a local variable, but it may also be allocated to the heap because it takes its address and passes it to fmt.Println
- depending on the compiler's judgment.
Overall, Go's memory allocation mechanism is smart enough to not require manual intervention in most cases. But when using pointers, understanding the difference between stack and heap and the basic principles of escape analysis can help write more efficient code. Basically that's it.
The above is the detailed content of Stack vs heap allocation with pointers in Go. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

The most efficient way to write a KubernetesOperator is to use Go to combine Kubebuilder and controller-runtime. 1. Understand the Operator pattern: define custom resources through CRD, write a controller to listen for resource changes and perform reconciliation loops to maintain the expected state. 2. Use Kubebuilder to initialize the project and create APIs to automatically generate CRDs, controllers and configuration files. 3. Define the Spec and Status structure of CRD in api/v1/myapp_types.go, and run makemanifests to generate CRDYAML. 4. Reconcil in the controller

Go does not have a built-in collection type, but it can be implemented efficiently through maps. Use map[T]struct{} to store element keys, empty structures have zero memory overhead, and the implementation of addition, inspection, deletion and other operations are O(1) time complexity; in a concurrent environment, sync.RWMutex or sync.Map can be combined to ensure thread safety; in terms of performance, memory usage, hashing cost and disorder; it is recommended to encapsulate Add, Remove, Contains, Size and other methods to simulate standard collection behavior.

UselightweightrouterslikeChiforefficientHTTPhandlingwithbuilt-inmiddlewareandcontextsupport.2.Leveragegoroutinesandchannelsforconcurrency,alwaysmanagingthemwithcontext.Contexttopreventleaks.3.OptimizeservicecommunicationbyusinggRPCwithProtocolBuffers

Usemulti-stageDockerbuildstocreatesmall,secureimagesbycompilingtheGobinaryinabuilderstageandcopyingittoaminimalruntimeimagelikeAlpineLinux,reducingsizeandattacksurface.2.Optimizebuildperformancebycopyinggo.modandgo.sumfirsttoleverageDockerlayercachin

Go and Kafka integration is an effective solution to build high-performance real-time data systems. The appropriate client library should be selected according to needs: 1. Priority is given to kafka-go to obtain simple Go-style APIs and good context support, suitable for rapid development; 2. Select Sarama when fine control or advanced functions are required; 3. When implementing producers, you need to configure the correct Broker address, theme and load balancing strategy, and manage timeouts and closings through context; 4. Consumers should use consumer groups to achieve scalability and fault tolerance, automatically submit offsets and use concurrent processing reasonably; 5. Use JSON, Avro or Protobuf for serialization, and it is recommended to combine SchemaRegistr

Go's template engine provides powerful dynamic content generation capabilities through text/template and html/template packages, where html/template has automatic escape function to prevent XSS attacks, so it should be used first when generating HTML. 1. Use {{}} syntax to insert variables, conditional judgments and loops, such as {{.FieldName}} to access structure fields, {{if}} and {{range}} to implement logical control. 2. The template supports Go data structures such as struct, slice and map, and the dot in the range represents the current iterative element. 3. The named template can be defined through define and reused with the template directive. 4.ht

When passing slices in Go, it is usually passed directly by value, because the slice header contains a pointer to the underlying array, and copying the slice header will not copy the underlying data, so the modification of elements in the function will affect the original slice; 1. If you need to reassign or adjust the slice length within the function and make the change take effect, you should pass the slice pointer; 2. Otherwise, you can pass the slice directly without using a pointer; 3. If reallocation may be triggered when using append, you must pass through the pointer to make the updated slice visible to the outside. Therefore, unless the entire slice is to be replaced, the slice should be passed in the form of a value.

govetcatchescommonlogicalerrorsandsuspiciousconstructsinGocodesuchas1)misuseofprintf-stylefunctionswithincorrectarguments,2)unkeyedstructliteralsthatmayleadtoincorrectfieldassignments,3)sendingtoclosedchannelswhichcausespanics,4)ineffectiveassignment
