What is the difference between buffered and unbuffered channels in Go?
Learn the difference between buffered and unbuffered channels in Go, their blocking behavior, and when to use each for safe goroutine synchronization.
Expected Interview Answer
An unbuffered channel has zero capacity, so a send blocks until another goroutine is ready to receive — the two goroutines synchronize on that exact moment. A buffered channel has a fixed capacity and lets sends proceed without a waiting receiver until the buffer is full.
You create them with make(chan T) for unbuffered and make(chan T, n) for a buffer of size n. An unbuffered channel guarantees a rendezvous: the send and receive happen at the same instant, making it a synchronization primitive. A buffered channel decouples sender and receiver in time — sends block only when the buffer is full and receives block only when it is empty. Choosing the wrong one causes either unnecessary blocking or hidden deadlocks and lost backpressure.
- Unbuffered channels give strong send/receive synchronization
- Buffered channels absorb short bursts and reduce goroutine stalls
- Buffer size acts as a natural backpressure limit
- Both are type-safe and safe for concurrent use
- Clear choice communicates intent about coupling between goroutines
AI Mentor Explanation
An unbuffered channel is like a relay throw where the fielder only releases the ball the instant the wicketkeeper's gloves are ready — both must meet at the same moment. A buffered channel is like a ball tray at the boundary: fielders can drop several balls in and keep playing, and the keeper collects them later, until the tray is full and they must wait.
Step-by-Step Explanation
Step 1
Create the channel
Use make(chan T) for an unbuffered channel or make(chan T, n) to give it a buffer of capacity n.
Step 2
Understand send behavior
On an unbuffered channel a send blocks until a receiver is ready; on a buffered channel it blocks only when the buffer is full.
Step 3
Understand receive behavior
A receive blocks until a value is available; a buffered channel can supply queued values immediately.
Step 4
Pick based on coupling
Use unbuffered for tight synchronization or handoff guarantees; use buffered to smooth bursts and add backpressure.
Step 5
Size the buffer deliberately
Choose capacity from expected burst size, not to hide a deadlock — an overly large buffer masks bugs and delays backpressure.
What Interviewer Expects
- Knows make(chan T) vs make(chan T, n) syntax
- Explains blocking semantics of send and receive for both
- Recognizes unbuffered channels as a synchronization point
- Understands buffered channels provide backpressure when full
- Can name when to choose each in real code
Common Mistakes
- Thinking a buffered channel never blocks
- Assuming unbuffered send happens before a receiver exists
- Using a large buffer to paper over a deadlock
- Confusing buffer capacity with the number of goroutines
- Forgetting that an unbuffered channel guarantees a rendezvous
Best Answer (HR Friendly)
“An unbuffered channel makes the sender wait until someone is ready to receive, so the two parts of the program stay in step. A buffered channel has a small waiting area, so the sender can drop off a few values and keep working until that space fills up.”
Code Example
// Unbuffered: send blocks until a receiver is ready
unbuf := make(chan int)
go func() { unbuf <- 1 }() // blocks until the receive below
fmt.Println(<-unbuf) // 1
// Buffered: two sends proceed without a receiver
buf := make(chan int, 2)
buf <- 1 // does not block, buffer has room
buf <- 2 // does not block, buffer now full
// buf <- 3 would block until a receive frees a slot
fmt.Println(<-buf, <-buf) // 1 2Follow-up Questions
- What happens when you send on a full buffered channel?
- How do you close a channel and what does a receive return afterward?
- When would an unbuffered channel cause a deadlock?
- How does select interact with buffered channels?
- What does cap() and len() report for a buffered channel?
MCQ Practice
1. What is the capacity of a channel created with make(chan int)?
make(chan int) with no size creates an unbuffered channel whose capacity is 0, so every send needs a ready receiver.
2. On a buffered channel with free space, a send operation will:
A buffered send only blocks when the buffer is full; with free space it completes immediately.
3. Which statement is true about unbuffered channels?
An unbuffered channel forces a rendezvous: the send completes exactly when a receiver takes the value.
Flash Cards
make(chan T) vs make(chan T, n) — make(chan T) is unbuffered (capacity 0); make(chan T, n) is buffered with capacity n.
When does an unbuffered send block? — Until another goroutine is ready to receive the value — it is a synchronization rendezvous.
When does a buffered send block? — Only when the buffer is already full.
Why prefer unbuffered channels? — They guarantee the sender and receiver meet, giving strong ordering and handoff synchronization.
What does buffer capacity provide? — It absorbs bursts and acts as backpressure — a full buffer forces the sender to wait.
Continue Learning
Related Interview Questions
What are channels in Go and how do they enable communication between goroutines?
medium
What is a Mutex in Go and how does it differ from a channel for synchronization?
medium
What is the Go memory model and what does the happens-before relationship mean?
hard
How do you detect and avoid race conditions in Go?
medium