Go interviews focus on goroutines, channels, interfaces, and error handling — the language is small, so questions go deep rather than wide. Below are the most common ones with model answers. Middle: deeper understanding, optimization, and real-world situations.
Try it — no account needed
Preparing your question…
Topics to prepare
✓Goroutines and the scheduler
✓Channels and select
✓Interfaces and composition
✓Error handling
✓Slices and maps
✓Context and cancellation
7 Middle-level questions with answers
1
What is the difference between a buffered and an unbuffered channel?
Answer
An unbuffered channel synchronises: the send blocks until a receiver takes the value, so both sides meet. A buffered channel accepts up to its capacity without a receiver, and blocks only when full. Unbuffered is the safer default because it makes the handoff explicit; a buffer is a decision about how much work may pile up.
2
When does a goroutine leak, and how would you notice?
Answer
When it blocks forever on a channel nobody will read or write, or waits on a context that is never cancelled. You notice by a goroutine count that climbs and never falls — runtime.NumGoroutine() or the pprof goroutine profile, which shows exactly where they are parked. The usual cause is a producer that returns early and leaves a consumer waiting.
3
What is `context` for?
Answer
Carrying a deadline, a cancellation signal and request-scoped values across API boundaries. Its real job is cancellation: when a request is abandoned, everything it started should stop rather than keep working for nobody. The rule that keeps it useful is that context is the first parameter and is never stored in a struct.
4
How does a `select` with a `default` behave differently from one without?
Answer
Without default, select blocks until one of its cases is ready. With default, it takes the default immediately if nothing else is, making the operation non-blocking. A default inside a loop with no other blocking is a busy-wait that will spin a core, which is the mistake to watch for.
5
What does the race detector find, and what does it not?
Answer
It finds concurrent access to the same memory where at least one is a write, on the code paths actually executed during the run. What it does not find is the race you did not exercise — it is a runtime tool, not a proof. Which is why it belongs in CI against real tests rather than being run once by hand.
6
How do you decide between a mutex and a channel?
Answer
A mutex protects shared state; a channel transfers ownership of data. If several goroutines read and write one structure, a mutex is simpler and faster. If the work moves from one goroutine to another, a channel expresses that directly. Reaching for a channel to guard a counter is a common overcomplication.
7
What does `sync.WaitGroup` guarantee, and how do you misuse it?
Answer
That Wait returns once the counter reaches zero, so you know every tracked goroutine finished. The two classic misuses are calling Add inside the goroutine, which races with Wait, and passing the WaitGroup by value, which copies it and leaves the original counter untouched. Both compile and both fail intermittently.
🦎
Reading answers is not enough
In a real interview you speak under pressure. Cam asks these same questions, scores every answer, and shows exactly what to fix.