← Back to Go Course | Chapter 5: Arrays Slices Maps | Lesson 2 of 7

Slices

A slice is like a flexible, expandable list -- unlike an array's fixed row of lockers, a slice can grow to hold as many items as you need.

Creating a Slice

A slice literal looks like an array literal but without a length, e.g. []int{1, 2, 3}. Internally it's a small structure pointing at an underlying array, tracking a length and capacity.

Example: Creating a Slice

markup
package main

import "fmt"

func main() {
	nums := []int{10, 20, 30}
	fmt.Println(nums, "len:", len(nums))
}

Slicing Syntax

You can create a new slice view over part of an existing slice or array using s[low:high], which selects elements from index low up to (but not including) high, sharing the same underlying memory.

Example: Slicing Syntax

markup
package main

import "fmt"

func main() {
	letters := []string{"a", "b", "c", "d", "e"}
	middle := letters[1:4]
	fmt.Println(middle)
}

Length vs Capacity

A slice's length is how many elements it currently holds; its capacity is how many elements the underlying array can hold starting from the slice's first element, which matters for how appending behaves.

Note: cap(s) tells you how much room a slice has to grow before a new underlying array must be allocated.

Example: Length vs Capacity

markup
package main

import "fmt"

func main() {
	s := make([]int, 2, 5)
	fmt.Println("len:", len(s), "cap:", cap(s))
}

Shared Underlying Arrays

Because a slice is a view over an array, two slices derived from the same source can share memory -- modifying an element through one slice can be visible through the other, which is a frequent source of subtle bugs.

Note: Use copy() or append on a fresh slice when you need a truly independent slice.

Example: Shared Underlying Arrays

markup
package main

import "fmt"

func main() {
	base := []int{1, 2, 3, 4}
	view := base[1:3]
	view[0] = 99
	fmt.Println("base:", base)
}
Common Mistakes
  1. Confusing a slice's length (len) with its capacity (cap), leading to surprises when appending near the boundary.
  2. Assuming two slices sharing the same underlying array are fully independent, then being confused when modifying one changes the other.
  3. Creating a slice with 'var s []int' and treating nil as an error state, when a nil slice is actually perfectly safe to read and append to.
Chapter Summary
  • A slice is a flexible, resizable view over an underlying array.
  • Slices have both a length (len) and a capacity (cap).
  • Slicing an existing array or slice (s[low:high]) shares the same underlying data.
  • A nil slice has length 0 and is safe to use -- it's not an error state.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.