# Slices, Arrays & Maps

Arrays in Go have a fixed length baked into their type — [5]int and [10]int are different types. Almost nobody uses arrays directly; the collection type you reach for is a slice, a resizable view over an underlying array that Go manages for you.

# Concept

A slice is three words: a pointer to backing storage, a length, and a capacity. len(s) is how many elements it holds; cap(s) is how many it could hold before the backing array needs to grow. A map is Go’s built-in hash table, declared map[KeyType]ValueType, with no guaranteed iteration order.

# Explanation

Build a slice with a literal, make, or by slicing an existing array/slice:

nums := []int{1, 2, 3}
buf := make([]int, 0, 10) // len 0, cap 10
sub := nums[1:3]          // shares backing storage with nums

append adds elements, growing the backing array (and reallocating) if capacity runs out:

nums = append(nums, 4, 5)

Because a slice shares its backing array with whatever it was sliced from, mutating through one slice can be visible through another — sub[0] = 99 also changes nums[1]. append breaks that sharing the moment it has to reallocate, which is a common source of subtle bugs when code assumes aliasing that silently stopped holding.

Maps work with indexing and a two-value form that reports whether a key was present, which matters because the zero value and “missing” look identical otherwise:

m := map[string]int{"a": 1}
v := m["a"]          // 1
v, ok := m["z"]      // 0, false — "z" isn't there, this isn't a zero value in disguise
m["b"] = 2
delete(m, "a")

for range walks both: index and value for a slice, key and value for a map (in random order — never rely on map iteration order).

# Usage

package main

import "fmt"

func wordCount(words []string) map[string]int {
    counts := make(map[string]int)
    for _, w := range words {
        counts[w]++
    }
    return counts
}

func main() {
    counts := wordCount([]string{"go", "is", "fun", "go", "is", "go"})
    fmt.Println(counts["go"]) // 3
}

counts[w]++ works even the first time a key is seen: reading a missing map key returns the value type’s zero value, 0 for int, so the increment starts from zero without any explicit initialization check.

A map only tells you counts — it has no memory of which key was inserted first, and range order over a map is explicitly random. If you need to break ties by first appearance, that has to come from somewhere else: build the counts once, then walk the original slice in order, tracking the best count seen so far and only replacing it when you find a strictly higher one.

# Exercise

Implement MostFrequent(words []string) string: return the string that appears most often in words. If there’s a tie, return the one that appears first in words among the tied candidates. words is never empty.

🔒 This site's search assistant runs a local AI model in your browser — no cloud AI, no tracking. See the ℹ️ in the chat panel for details.