Fundamentals 5 min read

Common Pitfalls When Using Go Slices and How to Avoid Them

This article explains three typical pitfalls of Go slices—ignoring the slice returned by append, unintentionally sharing the underlying array which can cause memory leaks, and the value‑copy behavior of for‑range loops—while also showing how to inspect slice internals using unsafe pointers.

Cognitive Technology Team
Cognitive Technology Team
Cognitive Technology Team
Common Pitfalls When Using Go Slices and How to Avoid Them

In Go, slices are built on top of dynamic arrays and are widely used like Java's ArrayList , but developers must be aware of several subtle issues.

Pitfall 1: Using append without assigning the returned slice – because append may allocate a new underlying array, the original slice reference can become stale, causing added elements to be invisible.

Example (illustrated with screenshots in the original article) shows that the new slice returned by append must replace the old one.

Pitfall 2: Slice slicing shares the underlying array, leading to memory‑leak risk – similar to Java 7's String.substring implementation, a small slice that still references a large backing array prevents the garbage collector from reclaiming the large memory.

The article demonstrates this with visual examples and notes that Java solved the issue with System.arraycopy ; in Go you should explicitly copy data using the copy function.

Pitfall 3: The loop variable in a for range iteration is a copy – modifying the loop variable does not affect the original slice element.

Code snippets show the output before and after the modification, confirming that the original slice remains unchanged.

Understanding the slice internals

The underlying data structure is type SliceHeader struct { Data uintptr; Len int; Cap int } . By converting a slice to *reflect.SliceHeader via unsafe.Pointer , you can read the length, capacity, and the raw pointer to the backing array.

Sample code prints the slice contents, length, capacity, and accesses the first three elements directly through C‑style pointer arithmetic:

fmt.Println("C pointer first element:", *((*int)(unsafe.Pointer(p.Data))))
fmt.Println("C pointer second element:", *((*int)(unsafe.Pointer(p.Data + unsafe.Sizeof(p.Data)))) )
fmt.Println("C pointer third element:", *((*int)(unsafe.Pointer(p.Data + 2*unsafe.Sizeof(p.Data)))) )

Summary

Go slices provide lightweight, efficient value semantics, but developers must remember to use the slice returned by append , avoid unintentionally sharing the backing array without copying, and be aware that for range variables are copies; otherwise subtle bugs and memory leaks may occur.

BackendMemory LeakappendUnsafeSlicesCopy
Cognitive Technology Team
Written by

Cognitive Technology Team

Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.