0% completed
Unbuffered and Buffered Channels
On This Page
Unbuffered Channels
Buffered Channels
len and cap
Deadlock: A Send Nobody Receives
Comparing the Two Kinds
Key Takeaways
A channel is a typed connection that lets one goroutine pass values to another goroutine. One goroutine sends a value into the channel with ch <- v, and another goroutine receives it with <-ch. The type of the channel fixes the type of every value it carries, so a chan string carries strings and nothing else.
Every channel also has a capacity, which is the number of values it can hold while no goroutine is receiving them. The capacity is set once, in the call to make, and it determines when a send or a receive has to wait. A channel made with make(chan string) has a capacity of zero, and a channel made with make(chan string, 3) has a capacity of three.
Those two kinds of channel behave differently enough to have their own names. The questions here are what each kind does when a sender or a receiver is not ready, how len and cap report on a channel, and what happens when a value can never be received.
Unbuffered Channels
A channel with a capacity of zero is called an unbuffered channel (a channel with no room to store values). The Go specification says that communication on an unbuffered channel succeeds only when both a sender and a receiver are ready. A send therefore waits until a receiver is ready, and a receive waits until a sender is ready.
The value passes directly from one goroutine to the other at the moment both are ready. This is a handoff: when the send completes, the sender knows that the receiver has the value. The program below shows that the waiting goes in both directions.
Output:
send completed after 100ms received order 2 after 100ms
In the first half, main sends immediately but the receiving goroutine is asleep, so the send waits 100 ms. In the second half, main receives immediately but the sending goroutine is asleep, so the receive waits 100 ms. Neither side can finish an operation on an unbuffered channel without the other side.
Buffered Channels
A channel with a capacity greater than zero is called a buffered channel (a channel with room to store a fixed number of values). Its storage, the buffer, is a first-in, first-out queue: values are received in the order they were sent. A send waits only when the buffer is full, and a receive waits only when the buffer is empty.
The difference shows clearly when the receiver is slower than the sender. In the program below, a receiving goroutine takes 100 ms to prepare each of three orders. The deliver function runs the same exchange twice, once on an unbuffered channel and once on a channel with a capacity of three.
Output:
capacity 0: sender free after 200ms capacity 0: all orders ready after 300ms capacity 3: sender free after 0s capacity 3: all orders ready after 300ms
With no buffer, the sender hands over order 1 at 0 ms, order 2 at 100 ms, and order 3 at 200 ms. It is free only after 200 ms. With a buffer of three, all three sends complete without waiting and the sender is free immediately. The receiver finishes at 300 ms in both cases, because the buffer changes when the sender may continue, not how fast the receiver works.
len and cap
The built-in function cap returns the capacity of a channel, and len returns the number of values currently in its buffer. For an unbuffered channel, both are always zero.
Output:
len 0 cap 3 len 2 cap 3 received order 1 len 1 cap 3
The two sends in main complete without any receiving goroutine, because the buffer has room. The receive takes order 1, the value sent first, and leaves one value in the buffer.
The value of len is correct only at the instant it is read. When other goroutines send and receive on the same channel, the count can change before the next line runs. Code such as if len(ch) < cap(ch) { ch <- v } can therefore still wait, because another goroutine may fill the last slot between the check and the send. Use len for logging and measurements, not to decide whether an operation will wait.
Deadlock: A Send Nobody Receives
A send on an unbuffered channel waits for a receiver. If no goroutine will ever receive, the send waits forever. A state in which no goroutine can make progress is called a deadlock. When every goroutine in the program is waiting in this way, the Go runtime detects it and stops the program with a fatal error.
func main() { orders := make(chan string) orders <- "order 1" // no goroutine will ever receive this value fmt.Println("sent") }
Run as a complete program, this main prints:
fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan send]: main.main()
The line goroutine 1 [chan send] says that the main goroutine was waiting in a channel send. A buffered channel gives the same error once its buffer is full. Sending four values into make(chan string, 3) with no receiver stops on the fourth send.
The runtime reports a deadlock only when every goroutine is blocked. If one goroutine waits forever on a channel while others keep running, nothing is printed, and that goroutine simply never ends. A buffer does not fix a program that has no receiver either. It only postpones the moment when the sender starts waiting.
Comparing the Two Kinds
| Unbuffered | Buffered | |
|---|---|---|
| Made with | make(chan T) | make(chan T, n) with n > 0 |
cap(ch) | 0 | n |
| Send waits until | A receiver takes the value | There is a free slot |
| Receive waits until | A sender offers a value | There is a value in the buffer |
| When a send completes | The receiver has the value | The value is stored in the buffer |
Choose an unbuffered channel when the sender needs to know that the value was received. Choose a buffered channel when the sender may continue before the receiver has taken each value, up to a known limit. The capacity should come from a reason, such as the number of results you expect. It should not be a guess made to stop a deadlock.
Key Takeaways
- A channel carries values of one type from one goroutine to another, in the order they were sent.
- On an unbuffered channel, a send and a receive each wait until the other side is ready.
- On a buffered channel, a send waits only when the buffer is full, and a receive waits only when it is empty.
lenreports how many values are in the buffer at one instant, andcapreports the capacity.- A send or receive that can never complete blocks its goroutine forever. If all goroutines block, the runtime stops with a deadlock error.
A channel passes values between two goroutines, and its capacity sets how many values the sender may send before the receiver takes them. With no capacity, sender and receiver must both be ready for every value. With a capacity of n, the sender may be up to n values ahead.
Reading Progress
0%
On This Page
Unbuffered Channels
Buffered Channels
len and cap
Deadlock: A Send Nobody Receives
Comparing the Two Kinds
Key Takeaways