Python → Go for coding interviews
You know exactly what you'd write in Python. This is what it is in Go — every container and idiom that comes up in a whiteboard problem, in one place, plus the five things Go does differently that will cost you a bug if nobody warns you.
Why bother writing interview code in Go at all? The short version →
Containers
Go ships a slice and a map. Everything else you build in a few lines or get from slices, sort, and container/heap.
xs = []xs := []int{}xs.append(v)xs = append(xs, v)v = xs.pop()v := xs[len(xs)-1]; xs = xs[:len(xs)-1]xs[i:j]slices.Clone(xs[i:j]) // xs[i:j] aliasesd = {}d := map[string]int{}d.get(k, 0)d[k] // missing key = zero valuek in d_, ok := d[k]d[k].append(v)d[k] = append(d[k], v) // nil slice appends fineCounter(xs)for _, x := range xs { cnt[x]++ }s = set()s := map[int]struct{}{}s.add(v); v in ss[v] = struct{}{}; _, ok := s[v]list (append / pop)slice (append / xs[:len-1])collections.dequeq = q[1:] // fine for BFSheapq.heappush / heappopcontainer/heap + 5 methods on your typepush -vLess(i, j) returns h[i] > h[j]bisect.bisect_left(xs, t)sort.SearchInts(xs, t) / slices.BinarySearch(a, b)struct{ a, b int } or [2]intd[(r, c)]d[[2]int{r, c}] // arrays compare; slices don'tIdioms
The one-liners. Most have a direct equivalent since Go 1.21/1.22; the arithmetic ones don't, and those are where Python habits bite.
xs.sort(key=lambda p: p[1])slices.SortFunc(xs, func(a, b P) int { return a.y - b.y })xs.sort()slices.Sort(xs)xs[::-1]slices.Reverse(xs) // in placefor i, x in enumerate(xs)for i, x := range xsfor i in range(n)for i := range n // Go 1.22+min(a, b)min(a, b) // built in since 1.21float('inf')math.MaxInt // ints don't have one-7 // 2 == -4-7 / 2 == -3 // truncates toward zero-7 % 3 == 2-7 % 3 == -1 // ((a % n) + n) % n to fix"".join(parts)var b strings.Builder; b.WriteString(s)for ch in sfor _, r := range s // runes; s[i] is a BYTElist(s)[]byte(s) (ASCII) / []rune(s) (Unicode)a, b = b, aa, b = b, a@functools.lru_cachememo := map[key]int{} + a closuresys.setrecursionlimit(…)not needed — goroutine stacks grow to 1 GBFive traps for Python developers
None of these are exotic. Each one is a wrong answer that compiles.
1. Slices alias
1row := grid[2] // a view, not a copy2row[0] = 9 // grid[2][0] is now 934a := []int{1, 2, 3, 4}5b := a[:2] // shares a's backing array6b = append(b, 99) // overwrites a[2]! a is now [1 2 99 4]
A slice is a pointer, a length and a capacity into a shared array. Reslicing shares; only an append that exceeds capacity copies. Python's xs[i:j] always copies, so this is the trap you'll hit first. Use slices.Clone or the three-index form xs[i:j:j] when you need a private copy.
2. The range variable is a copy
1for _, p := range points {2 p.x++ // p is a COPY; points is unchanged3}4for i := range points {5 points[i].x++ // index to mutate6}
for _, p := range hands you a copy of each element. Mutating it does nothing to the slice. Index in, or range over a slice of pointers.
3. A nil map panics on write
1var m map[string]int // nil2m["a"] = 1 // panic: assignment to entry in nil map3m := map[string]int{} // or make(map[string]int)
Reading a nil map is fine (you get zero values). Writing panics. A var m map[K]V declaration is the usual culprit — use a literal or make.
4. Map iteration order is random
1for k, v := range m { … } // order is RANDOMISED per run2// Need order? Collect the keys, slices.Sort them, then range.
Python dicts keep insertion order; Go maps deliberately don't, and the order changes between runs. Any algorithm whose output depends on iteration order is nondeterministic. Sort the keys when it matters.
5. Call heap.Push, not h.Push
1h := &IntHeap{5, 2, 8}2heap.Init(h)3heap.Push(h, 1) // heap.Push, never h.Push4x := heap.Pop(h).(int) // heap.Pop, never h.Pop
The five methods you write (Len, Less, Swap, Push, Pop) are the interface; the package functions do the sifting. Calling your own Push appends without restoring the heap property and nothing warns you.
Two things that aren't in the table
- Integer overflow is real. Python ints are unbounded; Go's
intis 64 bits. Writelo + (hi-lo)/2for a midpoint, and reach formath/bigonly when a problem truly needs it. - There's no set type, and that's fine.
map[T]struct{}is the idiom. It costs one line of wrapper if you wantAdd/Has— generics make that wrapper reusable.
The table gets you writing Go. The course gets you fluent.
Module 03 of Reach For builds every one of these containers from scratch with step-through diagrams of what the memory is doing, then the remaining modules use them for the actual patterns — with exercises, reference solutions, and a grading prompt for each.