interviewpath
  • 0day streak
  • 10total XP
  • Level 1
0/5

Unit 2 · Software engineering · Lesson 11 of 15

Go essentials

Go is widely used for infrastructure, cloud and networked services, and it is the language of the MIT 6.5840 distributed-systems labs. Interviews in Go probe slice and map semantics, interfaces and error values, and above all goroutines, channels, select and context cancellation without leaks or data races.
About 3 hFocus mode

Step 1: Learn the ideas

  • Slices: length, capacity, append and aliasing
  • Maps: nil maps, iteration order, concurrency
  • Interfaces, implicit satisfaction and nil interface values
  • Errors as values; wrapping, errors.Is and errors.As
  • Goroutines and goroutine leaks
  • Channels: buffering, closing, nil channels
  • select, timeouts and context cancellation
  • Memory model and the race detector

Why it matters

Go makes concurrency cheap to start and easy to get subtly wrong. In interviews conducted in Go, the recurring question is whether you can stop what you start: every goroutine needs an exit path, every request a deadline, every shared variable an owner or a lock. The other common bug class comes from value semantics: copying a slice copies a view, not the data.

Core ideas

  • Slices are a (pointer, length, capacity) header over an array. Slicing shares the backing array, and append writes in place when capacity allows and reallocates otherwise, so two slices cut from one array can overwrite each other's elements. Copy explicitly (slices.Clone, copy) or cap the capacity with a full slice expression s[lo:hi:hi] before handing out a sub-slice.
  • Maps refer to a runtime hash table. Reading a nil map returns zero values; writing to one panics. Iteration order is unspecified and varies between runs. Maps are unsafe when any goroutine writes concurrently; guard them with a mutex.
  • Interfaces are satisfied implicitly by method sets. An interface value pairs a dynamic type with a value and is nil only when both are, so returning a nil *MyError as an error produces a non-nil error. Keep interfaces small and define them where they are used.
  • Errors are ordinary return values. Add context with fmt.Errorf("load config: %w", err) and inspect with errors.Is (a sentinel) or errors.As (a type), never by matching message strings. Reserve panic for programming errors.
  • Goroutines and channels. A send on an unbuffered channel completes only when a receiver takes the value, synchronizing both sides; a buffered channel decouples them up to its capacity. Only the sender should close a channel. Receiving from a closed channel yields the zero value with ok == false, sending on one panics, and a nil channel blocks forever, which is useful for disabling a select case. A goroutine blocked forever is a leak the runtime never reclaims.
  • select and context. select waits on several channel operations and picks pseudo-randomly among the ready ones; a default case makes it non-blocking. Pass a context.Context as the first parameter of request-scoped functions, watch ctx.Done() in loops and selects, and always call the cancel function returned by context.WithCancel or context.WithTimeout.
  • Memory model and races. Channel operations, mutexes and sync/atomic create happens-before edges. Without them, concurrent access where one side writes is a data race, and races on multiword values such as slices, strings, maps and interfaces can corrupt memory rather than merely return stale data. go test -race reports races that occur during the run.

Since Go 1.22, modules declaring Go 1.22 or later get a fresh loop variable per iteration, removing the classic bug of goroutines all capturing the final value.

Common misconceptions

  • "Passing a slice copies its data." It copies the header; the callee can modify the caller's elements, and whether its appends are visible depends on capacity.
  • "A nil pointer returned as an error is a nil error." The interface holds a non-nil type, so err != nil is true.
  • "The race detector proves there are no races." It only finds races on code paths that execute during the run.
  • "Channels must be closed to be freed." Unreachable channels are garbage-collected; close one only to tell receivers that no more values will come.

How to approach it

Work through A Tour of Go, then write a pipeline that stops cleanly when its context is cancelled and a worker pool with a fixed number of goroutines. Run both under -race, remove a lock on purpose and read the report. Then extend them with timeouts, error propagation and graceful shutdown.

Suggested order

  1. 1Work through A Tour of Go (Basics, Methods and interfaces, Generics, Concurrency) and do the exercises; skim anything you already know.
  2. 2Read "Go Slices: usage and internals" and "Go maps in action"; write a test that shows append aliasing between two sub-slices and fix it with a full slice expression.
  3. 3Read "Working with Errors in Go 1.13" and the Errors section of Effective Go; refactor a small function to wrap errors with %w and test them with errors.Is and errors.As.
  4. 4Read the Concurrency section of Effective Go and "Go Concurrency Patterns: Pipelines and cancellation"; build a three-stage pipeline that can stop early without leaking goroutines.
  5. 5Read "Go Concurrency Patterns: Context"; add a per-request timeout to the pipeline and make every stage exit on ctx.Done().
  6. 6Read the advice and informal overview of The Go Memory Model and the "Typical Data Races" section of the race detector article; introduce a race into a worker pool, find it with go test -race and fix it.
  7. 7Optional, larger: MIT 6.5840 Lab 1 (MapReduce) is written in Go and exercises goroutines, RPC, locking and the race detector.

Step 2: Check off what you can do

Tap each one you can genuinely do or explain. Each earns 10 XP.

Step 3: Go deeper

  • A Tour of GoStart here

    The Go Project (go.dev)

    Section: Methods and interfaces; Concurrency

    Language fluency with runnable examples; do every exercise in the Methods and interfaces and Concurrency modules.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • The Go Blog (selected articles)

    The Go Project (go.dev)

    Section: Go Slices: usage and internals

    Slice headers, capacity and append; the maps, errors, context, pipelines and loop-variable articles are listed under this resource.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Effective Go

    The Go Project (go.dev)

    Section: Concurrency

    Idiomatic goroutines and channels, plus the Interfaces and Errors sections; it predates generics and modules.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • The Go Memory ModelStart here

    The Go Project (go.dev)

    Section: Informal Overview

    The happens-before guarantees of channels, mutexes and atomics, and why races on multiword values can corrupt memory.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • Data Race Detector (Go documentation)

    The Go Project (go.dev)

    Section: Typical Data Races

    Running go test -race and recognizing the common race shapes it reports.

    Open(opens in a new tab)Link responded, 5 Oct 2026

Step 4: Practice

Do the Tour exercises first; Equivalent Binary Trees and Web Crawler are the concurrency ones, and the crawler should end up with a mutex-guarded visited map and a clean termination condition. Then solve three LeetCode problems in Go to practice maps and slices: Group Anagrams with a map from a canonical key to slices, Time Based Key-Value Store with sort.Search over per-key slices, and LRU Cache with container/list plus a map. Outside LeetCode, write a worker pool that processes a channel of jobs with a fixed number of goroutines, stops on context cancellation and returns the first error, and run its tests with -race. The 6.5840 MapReduce lab is the larger follow-up.

Record attempts on each problem’s page (+15 XP, +10 more when solved on your own).

Step 5: Test yourself

Answer each one out loud or on paper before you finish the lesson.

  1. Question 1When does append modify the array that another slice also sees?
  2. Question 2What happens when you write to a nil map? Read from one?
  3. Question 3How does errors.As differ from errors.Is?
  4. Question 4Who should close a channel, and what happens on a send after close?
  5. Question 5How do you stop a goroutine that is blocked receiving from a channel?
  6. Question 6What changed about loop variables in Go 1.22?

You’re done when you can

  • Predict the output of an append-aliasing snippet and fix it two different ways.
  • Explain why a function returning a nil *MyError as error yields a non-nil error, and fix it.
  • Write a cancellable worker pool from scratch in under 30 minutes that passes go test -race.
  • Explain which operations create happens-before edges in Go and what a data race on a slice can do.

Finish the lesson

How confident do you feel?

Lesson complete!

+50 XP

Reviews will come up on the Practice tab so it sticks.

Your notes and study time

Log study time