Skip to main content

Go Ep 4: Arrays, Slices & Memory Capacity

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
go - This article is part of a series.
Part 4: This Article
In Go, an Array has a fixed length determined at compile time. A Slice is a lightweight, dynamically sized view into an underlying array. Understanding slice capacity (cap) prevents accidental memory reallocation overhead.

TL;DR (Quick Summary)
#

  • Array: Fixed length ([5]int). Length is part of its type! Passing an array to a function copies the entire array memory.
  • Slice: Dynamic length ([]int). Under the hood, a slice is a 3-word struct: Pointer to underlying array, Length (len), and Capacity (cap).
  • Slice Header: Passing a slice to a function copies ONLY the 24-byte Slice Header, not the underlying array data.
  • append() Reallocation: When len == cap, calling append() allocates a new, larger array (usually doubling capacity) and copies the elements over.

1. Slice Header Memory Architecture
#

Under the hood in Go runtime source code, a Slice is represented by SliceHeader:


graph TD
    subgraph Slice Header (24 Bytes)
        DataPtr["*Data Pointer"] --> Element0
        Len["Length: 3"]
        Cap["Capacity: 5"]
    end

    subgraph UnderlyingArrayMemory ["Underlying Array Memory"]
        Element0["Index 0: 'A'"]
        Element1["Index 1: 'B'"]
        Element2["Index 2: 'C'"]
        Element3["Index 3: Allocated / Empty"]
        Element4["Index 4: Allocated / Empty"]
    end

2. Comparison: Arrays vs Slices
#

FeatureArray ([N]T)Slice ([]T)
Size DefinitionFixed at compile time ([5]int).Dynamic at runtime (make([]int, 5)).
Type Equality[5]int and [10]int are completely different types![]int is a single uniform type.
Memory PassingCopies the whole memory block (Heavy).Copies only the 24-byte Slice Header (Lightweight).
Resizing SupportImpossible.Supported via append().

3. Step-by-Step Lab: Inspecting Slice len and cap Growth
#

Let’s observe how append() dynamically doubles capacity when limits are reached.

Step 3.1: Writing the Slice Inspection Code
#

Create main.go:

package main

import "fmt"

func inspectSlice(s []int, name string) {
	fmt.Printf("%s -> len: %d, cap: %d, data: %v\n", name, len(s), cap(s), s)
}

func main() {
	// 1. Create slice with make(type, len, cap)
	numbers := make([]int, 0, 2) // Length 0, Capacity 2
	inspectSlice(numbers, "Initial")

	// 2. Append elements within capacity limit
	numbers = append(numbers, 10)
	inspectSlice(numbers, "Append 1")

	numbers = append(numbers, 20)
	inspectSlice(numbers, "Append 2")

	// 3. Exceed capacity! Watch capacity DOUBLE!
	numbers = append(numbers, 30)
	inspectSlice(numbers, "Append 3 (Exceeded Cap)")

	// 4. Slicing an existing slice [start:end]
	subSlice := numbers[1:3]
	inspectSlice(subSlice, "SubSlice [1:3]")
}

Step 3.2: Executing the Code
#

Run the application:

go run main.go

Expected Terminal Output:

Initial -> len: 0, cap: 2, data: []
Append 1 -> len: 1, cap: 2, data: [10]
Append 2 -> len: 2, cap: 2, data: [10 20]
Append 3 (Exceeded Cap) -> len: 3, cap: 4, data: [10 20 30]
SubSlice [1:3] -> len: 2, cap: 3, data: [20 30]

Notice how Append 3 automatically doubled the capacity from 2 to 4 to accommodate the new element!


4. Troubleshooting & Common Errors
#

Error 1: panic: runtime error: index out of range
#

The Cause: Accessing a slice index greater than or equal to len(slice), even if cap(slice) is large enough!

s := make([]int, 0, 10)
s[0] = 42 // 💥 Panic! len is 0.

// 🟢 Fix: Use append() or set len in make()
s := make([]int, 10, 10)
s[0] = 42 // Works perfectly!

Summary & Next Steps
#

In this episode:

  • We analyzed fixed Arrays vs dynamic Slices.
  • We dissected the 24-byte SliceHeader (ptr, len, cap).
  • We observed capacity doubling during append() reallocations.

In Episode 5: Maps & Structs, we will master Go key-value Hash Maps and custom composite Structs!

go - This article is part of a series.
Part 4: This Article