Skip to main content
An unbuffered channel in Go is a typed conduit for synchronous communication between goroutines, characterized by having zero capacity to store data. Because it lacks an internal buffer, a send operation on an unbuffered channel blocks the sending goroutine until another goroutine executes a corresponding receive operation on the same channel, and vice versa. This creates a strict rendezvous point where data is handed off directly from the sender to the receiver.

Syntax

An unbuffered channel is instantiated using the built-in make function without specifying a capacity argument, or by explicitly setting the capacity to 0.

Execution Mechanics

The defining characteristic of an unbuffered channel is its strict synchronization guarantee. The Go runtime manages this through the scheduler:
  1. Send Operation (ch <- data): When a goroutine attempts to send data into an unbuffered channel, the Go scheduler pauses that goroutine. It remains in a waiting state until a different goroutine executes a receive operation on the exact same channel.
  2. Receive Operation (<-ch): Conversely, if a goroutine attempts to read from an unbuffered channel before any data has been sent, the scheduler pauses the receiving goroutine until a sender becomes available.
  3. The Handoff: Once both a sender and a receiver are ready at the same time, the data is copied directly from the sending goroutine’s memory stack to the receiving goroutine’s memory stack. No intermediate queuing or buffering occurs.

Visualization of Blocking Behavior

To prevent the main goroutine from exiting before the receiving goroutine completes its execution, a secondary synchronization mechanism (like a done channel) is required.

Deadlock Conditions

Because unbuffered channels require simultaneous participation from both a sender and a receiver, they are highly susceptible to deadlocks if the complementary operation is never executed. If a single goroutine attempts to send to or receive from an unbuffered channel without another concurrent goroutine available to fulfill the opposite side of the transaction, the operation will block indefinitely. If the Go runtime detects that all active goroutines are asleep and waiting on channel operations, it will crash the program with a fatal error: all goroutines are asleep - deadlock! panic.
Tired of Poor Go Skills? Fix That With Deep Grasping!Learn More