Arrays, Slices & Maps
Work with Go's fundamental collection types: fixed-size arrays, dynamic slices, and hash maps.
Arrays
Arrays in Go are fixed-size sequences of elements of the same type, where the size is part of the type itself. This means [5]int and [10]int are different types and cannot be assigned to each other. Arrays are value types in Go, so assigning an array to another variable copies all elements. Because of their fixed size, arrays are rarely used directly in Go — slices are preferred for most use cases.
package main
import "fmt"
func main() {
// Declare and initialize
var numbers [5]int
numbers[0] = 10
numbers[1] = 20
// Array literal
primes := [5]int{2, 3, 5, 7, 11}
// Compiler counts elements
vowels := [...]string{"a", "e", "i", "o", "u"}
fmt.Println("numbers:", numbers)
fmt.Println("primes:", primes)
fmt.Println("vowels:", vowels)
fmt.Println("length:", len(primes))
// Arrays are value types (copied on assignment)
original := [3]int{1, 2, 3}
copy := original
copy[0] = 99
fmt.Println("original:", original) // [1 2 3]
fmt.Println("copy:", copy) // [99 2 3]
}
Slices
Slices are the workhorse collection type in Go, providing a flexible, dynamic view into an underlying array. Unlike arrays, slices have a dynamic length and are reference types, meaning they point to the same underlying data when assigned or passed to functions. A slice has three components: a pointer to the underlying array, a length, and a capacity. You can create slices using literals, the 'make' function, or by slicing an existing array or slice.
package main
import "fmt"
func main() {
// Slice literal
fruits := []string{"apple", "banana", "cherry"}
// Create with make(type, length, capacity)
scores := make([]int, 3, 10)
scores[0] = 90
scores[1] = 85
scores[2] = 92
// Append elements (may allocate new underlying array)
fruits = append(fruits, "date", "elderberry")
// Slicing
fmt.Println(fruits[1:3]) // [banana cherry]
fmt.Println(fruits[:2]) // [apple banana]
fmt.Println(fruits[3:]) // [date elderberry]
fmt.Printf("len=%d cap=%d %v\n", len(scores), cap(scores), scores)
// Copy slices
src := []int{1, 2, 3}
dst := make([]int, len(src))
copied := copy(dst, src)
fmt.Printf("Copied %d elements: %v\n", copied, dst)
}
Maps
Maps in Go are hash tables that store key-value pairs with O(1) average lookup time. Maps must be initialized before use, either with a map literal or the 'make' function — a nil map will panic on write operations. The comma-ok idiom lets you distinguish between a missing key and a zero value. Maps are not safe for concurrent access; you need sync.Mutex or sync.Map for concurrent scenarios.
package main
import "fmt"
func main() {
// Map literal
colors := map[string]string{
"red": "#ff0000",
"green": "#00ff00",
"blue": "#0000ff",
}
// Create with make
scores := make(map[string]int)
scores["Alice"] = 95
scores["Bob"] = 87
// Access and check existence
hex := colors["red"]
fmt.Println("Red:", hex)
// Comma-ok idiom
value, exists := colors["purple"]
if !exists {
fmt.Println("purple not found, got zero value:", value)
}
// Delete a key
delete(scores, "Bob")
// Iterate over a map
for key, val := range colors {
fmt.Printf("%s -> %s\n", key, val)
}
fmt.Println("Map length:", len(colors))
}
Iteration Patterns
Go provides consistent iteration patterns across its collection types using the 'range' keyword. When ranging over slices, you get the index and a copy of the element at that index. For maps, you get the key and value. If you only need the index or key, you can omit the second variable. If you only need the value, use the blank identifier '_' for the index to avoid compiler errors about unused variables.
package main
import (
"fmt"
"sort"
)
func main() {
names := []string{"Charlie", "Alice", "Bob"}
// Sort a slice
sort.Strings(names)
fmt.Println("Sorted:", names)
// Filter pattern
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var evens []int
for _, n := range numbers {
if n%2 == 0 {
evens = append(evens, n)
}
}
fmt.Println("Evens:", evens)
// Map transformation pattern
words := []string{"hello", "world", "go"}
lengths := make(map[string]int)
for _, w := range words {
lengths[w] = len(w)
}
fmt.Println("Lengths:", lengths)
// Iterating with index only
for i := range names {
fmt.Printf("Index %d: %s\n", i, names[i])
}
}