Arrays — Fixed Size
Go arrays have a fixed size that's part of the type. [3]int and [5]int are different types. Arrays are value types — assigning or passing copies the entire array. In practice, you rarely use arrays directly; slices are much more common.
// Declare and initialize
var a [5]int // [0 0 0 0 0] (zero values)
b := [3]string{"go", "is", "fun"}
c := [...]int{10, 20, 30} // Size inferred from elements
fmt.Println(a)
fmt.Println(b)
fmt.Println(len(c)) // 3
[0 0 0 0 0] [go is fun] 3
Slices — Dynamic, Powerful
Slices are Go's workhorse data structure. They're dynamic-length views into underlying arrays. A slice has three components: a pointer to the array, a length (how many elements), and a capacity (how many elements the underlying array can hold).
// Create slices
s := []int{1, 2, 3, 4, 5} // Slice literal (no size = slice, not array)
s2 := make([]int, 5) // make(type, length) - [0 0 0 0 0]
s3 := make([]int, 0, 10) // make(type, length, capacity)
fmt.Printf("s: len=%d cap=%d %v\n", len(s), cap(s), s)
fmt.Printf("s3: len=%d cap=%d %v\n", len(s3), cap(s3), s3)
s: len=5 cap=5 [1 2 3 4 5] s3: len=0 cap=10 []
append — Growing Slices
s := []int{1, 2, 3}
s = append(s, 4) // Add one element
s = append(s, 5, 6, 7) // Add multiple
fmt.Println(s) // [1 2 3 4 5 6 7]
// Append another slice with ...
more := []int{8, 9}
s = append(s, more...)
fmt.Println(s) // [1 2 3 4 5 6 7 8 9]
When append exceeds the capacity, Go allocates a new, larger underlying array and copies elements. This is amortized O(1) but can cause unexpected behavior if you hold references to the old slice.
Slicing — Creating Sub-slices
s := []int{0, 1, 2, 3, 4, 5}
fmt.Println(s[1:4]) // [1 2 3] (index 1 to 3, exclusive end)
fmt.Println(s[:3]) // [0 1 2] (first 3)
fmt.Println(s[3:]) // [3 4 5] (from index 3)
fmt.Println(s[:]) // [0 1 2 3 4 5] (copy of entire slice)
⚠️ Common Mistake: Sub-slices share memory
A sub-slice shares the same underlying array. Modifying s[1:3] also modifies s! To get an independent copy, use copy():
original := []int{1, 2, 3, 4, 5}
independent := make([]int, 3)
copy(independent, original[1:4]) // independent copy of [2 3 4]
make() when you know the size, or literals when you have values. Always reassign the result of append: s = append(s, val).Practice Exercises
Easy Hello World Variant
Modify the example to accept user input and print a personalized greeting.
Easy Code Reading
Read through the code examples above and predict the output before running them.
Medium Extend the Example
Take one code example and add error handling, input validation, or a new feature.