Go Cheatsheet
Slices and Maps
Use this Go reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Slices — Overview
A slice is a descriptor (pointer, length, capacity) over an underlying array. It is the primary dynamic collection in Go.
var s []int // nil slice (len=0, cap=0) s := []int{} // empty (non-nil, len=0, cap=0) s := []int{1, 2, 3} // literal s := make([]int, 5) // len=5, cap=5, zeroed s := make([]int, 3, 10) // len=3, cap=10
Slice Operations
s := []int{10, 20, 30, 40, 50} len(s) // 5 — number of elements cap(s) // capacity of underlying array s[0] // 10 s[1:3] // [20 30] — half-open [low:high) s[:2] // [10 20] — from start s[2:] // [30 40 50] — to end s[:] // full copy of the slice header (same backing array)
append
s = append(s, 60) // append single s = append(s, 70, 80) // append multiple s = append(s, other...) // append another slice
When the underlying array overflows, Go allocates a new one (typically 2× capacity). Always reassign:
s = append(s, v).
copy
dst := make([]int, len(src)) n := copy(dst, src) // copies min(len(dst), len(src)) elements; returns n copied
delete element at index i
// Preserves order — O(n) s = append(s[:i], s[i+1:]...) // Unordered (swap with last) — O(1) s[i] = s[len(s)-1] s = s[:len(s)-1]
insert at index i
s = append(s[:i+1], s[i:]...) s[i] = value
Iterating Slices
for i, v := range s { fmt.Println(i, v) } for i := range s { // index only s[i] *= 2 }
Multi-dimensional Slices
matrix := [][]int{ {1, 2, 3}, {4, 5, 6}, } matrix[1][2] // 6 // Allocate dynamically rows, cols := 3, 4 m := make([][]int, rows) for i := range m { m[i] = make([]int, cols) }
Slice Gotchas
// Slices share the underlying array a := []int{1, 2, 3, 4} b := a[1:3] // b = [2 3], shares a's array b[0] = 99 // a is now [1 99 3 4] // To get an independent copy: c := append([]int(nil), a...) // or copy into make() // Full slice expression — limits capacity to prevent sharing b = a[1:3:3] // len=2, cap=2; append to b won't clobber a // nil slice vs empty slice var n []int // nil; len=0, n==nil → true e := []int{} // empty; len=0, e==nil → false // Both are safe to range over, append to, pass to len/cap
Sorting Slices
import "sort" ints := []int{3, 1, 4, 1, 5} sort.Ints(ints) // ascending in-place sort.Sort(sort.Reverse(sort.IntSlice(ints))) // descending strs := []string{"banana", "apple"} sort.Strings(strs) // Custom comparator sort.Slice(ints, func(i, j int) bool { return ints[i] < ints[j] // ascending }) sort.SliceStable(ints, func(i, j int) bool { ... }) // stable sort // Generic sort (Go 1.21+) import "slices" slices.Sort(ints) slices.SortFunc(ints, func(a, b int) int { return cmp.Compare(a, b) })
slices Package (Go 1.21+)
import "slices" slices.Contains(s, v) // true if v in s slices.Index(s, v) // first index of v, -1 if absent slices.Max(s) // maximum element slices.Min(s) // minimum element slices.Equal(a, b) // element-wise equality slices.Reverse(s) // reverse in-place slices.Compact(s) // remove consecutive duplicates slices.Delete(s, i, j) // delete s[i:j] slices.Insert(s, i, v...) // insert at i slices.Clone(s) // shallow copy slices.Grow(s, n) // ensure cap >= len+n slices.Clip(s) // trim excess capacity slices.BinarySearch(s, v) // (index, found) for sorted slice
Maps — Overview
A map is an unordered collection of key-value pairs. Keys must be comparable (==).
var m map[string]int // nil map; read OK, write PANICS m := map[string]int{} // empty map (non-nil) m := map[string]int{ // literal "alice": 25, "bob": 30, } m := make(map[string]int) // empty m := make(map[string]int, 100) // with capacity hint
Map Operations
m := map[string]int{"a": 1} // Read (zero value if absent) v := m["a"] // 1 v = m["z"] // 0 (zero value) // Comma-ok idiom v, ok := m["a"] // ok=true v, ok = m["z"] // ok=false // Write m["b"] = 2 // Delete delete(m, "a") // Length len(m) // Iterate (order is random) for k, v := range m { fmt.Println(k, v) } for k := range m { ... } // keys only
Checking Existence
if v, ok := m[key]; ok { fmt.Println("found:", v) } else { fmt.Println("missing") }
maps Package (Go 1.21+)
import "maps" maps.Keys(m) // iterator over keys maps.Values(m) // iterator over values maps.Clone(m) // shallow copy maps.Delete(m, func(k, v T) bool { ... }) // conditional delete maps.Equal(m1, m2) // key-value equality maps.Copy(dst, src) // merge src into dst
Common Map Patterns
Counting / frequency map
words := strings.Fields("the cat sat on the mat the") freq := make(map[string]int) for _, w := range words { freq[w]++ }
Grouping (map of slices)
byLen := make(map[int][]string) for _, w := range words { byLen[len(w)] = append(byLen[len(w)], w) }
Set (map to struct{})
seen := make(map[string]struct{}) seen["alice"] = struct{}{} _, exists := seen["alice"] // true
Default value with mutex (concurrent)
import "sync" var mu sync.Mutex m := make(map[string]int) mu.Lock() m["key"]++ mu.Unlock() // Or use sync.Map for concurrent access without explicit locking var sm sync.Map sm.Store("key", 42) v, ok := sm.Load("key") sm.Delete("key") sm.Range(func(k, v any) bool { fmt.Println(k, v) return true // continue iteration })
Maps Are Reference Types
a := map[string]int{"x": 1} b := a // b references the same map b["x"] = 99 fmt.Println(a["x"]) // 99
Nested Maps
graph := map[string]map[string]int{ "a": {"b": 1, "c": 2}, "b": {"c": 3}, } graph["a"]["b"] // 1 // Always initialize inner map before writing if graph["d"] == nil { graph["d"] = make(map[string]int) } graph["d"]["e"] = 5
Map Gotchas
// Writing to a nil map panics var m map[string]int m["key"] = 1 // PANIC: assignment to entry in nil map // Map is not safe for concurrent read+write // Use sync.Mutex or sync.Map // Map iteration order is randomized — never rely on it // Keys can be any comparable type: int, string, struct (no slice/map/func) // Deleting during range is safe in Go for k := range m { if condition(k) { delete(m, k) } }