# Start Here: One Simple Mental Model
Arrays, slices, and maps are related, but they solve different problems:
- Array = actual fixed-size storage
- Slice = flexible view over storage
- Map = key-based lookup table
Beginners should focus on when to use each. Senior engineers should focus on memory, ownership, mutation, iteration behavior, and edge cases.
# Arrays — Fixed Size and Value Semantics
Arrays have fixed size, and the size is part of the type. This means [3]int and [4]int are different types.
var a [3]int
b := [3]int{10, 20, 30}
c := [...]int{1, 2, 3, 4}
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(len(c))Arrays are less common in everyday service code, but they appear in hashes, protocol formats, fixed-size tables, and places where value semantics are useful.
# Slices — The Most Important Collection in Go
Slices are what you use most of the time. They are not the data itself. They are a descriptor of where data starts, how much is visible, and how much spare room exists.
s1 := []int{1, 2, 3}
s2 := make([]int, 5)
s3 := make([]int, 3, 10)
fmt.Println(s1)
fmt.Println(len(s2), cap(s2))
fmt.Println(len(s3), cap(s3))▸ Easy analogy: a slice is a window, not a new room
# The Sharing Gotcha Everyone Must Understand
Slices usually share backing arrays. This is the most important slice concept for interviews and real-world debugging.
a := []int{1, 2, 3, 4, 5}
b := a[1:3]
b[0] = 99
fmt.Println(a) // [1 99 3 4 5]
fmt.Println(b) // [99 3]b starts at a[1], so writing to b[0] changes a[1] too. If you need independence, copy the slice.
# Append, Capacity, and Reallocation
append may reuse the same backing array or allocate a new one. That depends on capacity.
s := []int{1, 2, 3}
s = append(s, 4, 5)
fmt.Println(s)Always capture the returned value. append is allowed to return a new slice header pointing at a new backing array.
# Nil Slice vs Empty Slice
var a []int
b := []int{}
fmt.Println(a == nil) // true
fmt.Println(b == nil) // false
fmt.Println(len(a), len(b)) // 0 0Both often behave similarly, but they are not identical. This matters for APIs, marshaling, and edge-case correctness.
# Copying Slices Safely
If you need to prevent shared mutation, make a copy.
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
dst[0] = 999
fmt.Println(src)
fmt.Println(dst)# Maps — Lookup, Grouping, Counting
Maps are the right tool for fast lookup by key, counting, deduplication, indexing, and grouping.
ages := map[string]int{
"Alice": 30,
"Bob": 25,
}
ages["Carol"] = 28
delete(ages, "Bob")
age, ok := ages["Dave"]
fmt.Println(age, ok)Use the two-value form when zero values are meaningful. For example, 0 may mean either “missing” or “present and zero”.
# Nil Map vs Empty Map
Reading from a nil map is okay. Writing to a nil map panics.
var m map[string]int
fmt.Println(m["x"]) // 0
m = make(map[string]int)
m["x"] = 1
fmt.Println(m["x"]) // 1# Most Asked Practical Scenarios
Frequency counting
words := []string{"go", "is", "go", "fun", "go"}
freq := make(map[string]int)
for _, w := range words {
freq[w]++
}Deduplicate a slice
seen := make(map[int]bool)
out := make([]int, 0, len(nums))
for _, n := range nums {
if !seen[n] {
seen[n] = true
out = append(out, n)
}
}Delete by index from a slice
s = append(s[:i], s[i+1:]...)In-place filtering
func filterEvens(nums []int) []int {
out := nums[:0]
for _, n := range nums {
if n%2 == 0 {
out = append(out, n)
}
}
return out
}# Edge Cases Senior Engineers Care About
- Map iteration order is unspecified — sort keys when order matters.
- Sub-slicing large buffers can retain large backing arrays unexpectedly.
- Use three-index slicing when you want to limit shared capacity.
- Arrays can be map keys; slices cannot.
- Maps are not safe for concurrent writes without synchronization.
- Nil vs empty slices can affect JSON and public API semantics.
⚡ Key Takeaways
- Arrays are fixed-size value types.
- Slices are views over arrays, so sharing and capacity matter.
- Always reassign the result of
append. - Use
v, ok := m[key]when key presence matters. - Never write to a nil map.
- Copy slices when you need ownership isolation.