DEV Community

Cover image for ✂️ Understanding Slices in Go: A Beginner’s Guide
Joseph utuedeye
Joseph utuedeye

Posted on

✂️ Understanding Slices in Go: A Beginner’s Guide

When I started learning Go, arrays made sense, fixed-length, type-specific, easy.
Then I met slices… and I was like

“Wait… it looks like an array🤔, but it isn’t? It can grow. What’s the difference?”

If you've asked the same questions, this guide is for you.

🧠 What is a Slice?

A slice in Go is a flexible, growable view into the elements of an array.

It’s built on top of an array, but unlike arrays, slices can change size.

Example:

nums := []int{1, 2, 3, 4}
Enter fullscreen mode Exit fullscreen mode

Here, nums is a slice of integers. You didn’t define how long it should be. Go figure that out.

🔍 The Anatomy of a Slice

Under the hood, a slice has three parts:

  1. Pointer – to the underlying array
  2. Length – number of elements in the slice
  3. Capacity – total space from the starting index to the end of the array
s := []int{1, 2, 3, 4, 5}
fmt.Println(len(s)) // 5
fmt.Println(cap(s)) // 5
Enter fullscreen mode Exit fullscreen mode

You can change how much of a slice you want to see:

part := s[1:4] // Includes s[1], s[2], s[3] => [2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

🛠 How to Create Slices

1. From an Array

arr := [5]int{10, 20, 30, 40, 50}
slice := arr[1:4] // [20, 30, 40]
Enter fullscreen mode Exit fullscreen mode

2. Using a Slice Literal

words := []string{"go", "is", "cool"}
Enter fullscreen mode Exit fullscreen mode

3. Using make()

numbers := make([]int, 3, 5)
// len = 3, cap = 5 => [0, 0, 0]
Enter fullscreen mode Exit fullscreen mode

➕ Appending to a Slice

Slices grow using the append() function:

letters := []string{"a", "b"}
letters = append(letters, "c", "d") // ["a", "b", "c", "d"]
Enter fullscreen mode Exit fullscreen mode

Behind the scenes, Go may allocate a new underlying array if the slice exceeds its capacity.

⚠️ Common Gotchas

1. Slices Share the Same Underlying Array

s1 := []int{1, 2, 3}
s2 := s1
s2[0] = 99

fmt.Println(s1) // [99 2 3]
Enter fullscreen mode Exit fullscreen mode

Both s1 and s2 point to the same data.

2. Slicing Can Limit Capacity

base := []int{1, 2, 3, 4, 5}
part := base[1:3]           // [2, 3]
part = append(part, 100, 200) // might overwrite base[3] and base[4]!
Enter fullscreen mode Exit fullscreen mode

To avoid this, use copy():

safe := make([]int, len(part))
copy(safe, part)
Enter fullscreen mode Exit fullscreen mode

✅ Recap

  • Slices are flexible views into arrays.
  • They have length and capacity.
  • You can create slices using literals, arrays, or make().
  • Use append() to grow slices.
  • Be cautious: slices share memory!

🔚 Final Thoughts

Understanding slices is key to writing clean and efficient Go code. They might look like arrays at first, but they’re way more powerful and a bit trickier under the hood.

But now you know the difference, and you're ready to slice and dice like a pro 😄. 🍕

Top comments (0)