How Go Channels Coordinate Goroutines
What are channels in Go, and how do they work? Explain the difference between buffered and unbuffered channels.
what they're testing: The interviewer is probing whether you can reason about communication, synchronization, and blocking in concurrent Go code.
Channels let goroutines exchange typed values and synchronize their work. Create one with make(chan T), send with ch <- v, and receive with <-ch. When an operation cannot proceed, it blocks the goroutine performing it, not every goroutine in the program.
An unbuffered send can proceed only when a receiver is ready, so the handoff synchronizes the two goroutines. A buffered channel can hold up to its fixed capacity. Sends proceed while space remains and block when the buffer is full. Receives from an open channel block when the buffer is empty. This bounded buffer can provide backpressure, but it is not an unbounded message queue. A select considers several channel operations and chooses one that can proceed.
Closing a channel records that no more values will be sent; it is not required for garbage collection. Receivers first drain any buffered values. After that, receives return the element type's zero value immediately, with ok == false in v, ok := <-ch. Sending to a closed channel panics. Sending or receiving on a nil channel blocks forever. A nil channel can disable a select case, but using one accidentally can cause a deadlock.
Where people slip
the tempting wrong answer, and what's actually true
Channels are just thread-safe, unbounded queues.
A channel has zero or fixed buffer capacity, and its send and receive operations also provide synchronization.
An unbuffered send stores the value until a receiver reads it later.
An unbuffered send blocks until a receiver is ready to receive the value.
Closing a channel releases its resources, so every channel must be closed.
Closing does not release channel resources. It signals that no more values will be sent, so a channel only needs to be closed when receivers must observe that signal.
Receiving from a closed channel always panics.
A receive drains any buffered values, then returns the element type's zero value immediately with `ok` set to false.
If they push further
What does `select` do when several cases are ready?
It chooses one ready communication using uniform pseudo-random selection; if none is ready, it uses `default` or blocks when there is no `default`.
Who should close a channel?
The sending side that knows no more values will be produced should usually close it, because sending to or closing an already closed channel panics.
What happens when you send to or receive from a nil channel?
Both operations block forever. In a `select`, a case using a nil channel can never proceed, so setting a channel to nil can deliberately disable that case.
Sources
- Go: A Tour of Go - Channels ↗go.dev
- Go: The Go Programming Language Specification ↗go.dev
- Go: Effective Go - Channels ↗go.dev
- Go: The Go Memory Model ↗go.dev
Now answer it yourself.
Reading a strong answer is easy. Producing one under pressure is the skill the interview tests. Gapmap grades your answer against the same bar an interviewer would.
beta
The interviewer part is in the works.
The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.