Explanation
What just happened
An unbuffered channel has no room to hold a value. So ch <- "hello" couldn’t finish until the receiver arrived at <-ch. main sat in [chan send] the whole time the receiver was busy. When the receiver got there, the value went straight across and both carried on.
That’s the point of an unbuffered channel: the send and the receive happen together, so the sender knows the value was taken.
Try the what-if switch
- buffer of 1:
make(chan string, 1)has room for one value. The send dropped it in the buffer and returned at once, sosentprinted while the receiver was still asleep.
Which to use
Unbuffered when you want the handoff to sync the two goroutines. Buffered when the sender shouldn’t wait for each value, for example a queue of jobs.
Watch out
A buffer only moves the wait. Once it’s full, the next send waits exactly like an unbuffered one.
Common questions
Does sending on an unbuffered channel block?
Yes. The send waits until a receiver takes the value. A goroutine dump shows the sender as [chan send].
When does a buffered channel block?
A send waits only when the buffer is full, and a receive only when it's empty. With room left, ch <- v returns at once.
What is all goroutines are asleep - deadlock?
The Go runtime found every goroutine waiting, with nothing left that could wake any of them. It stops the program with this fatal error and exit code 2, and prints where each goroutine was waiting.
Verified: this timeline matches a real program, checked in CI on Go 1.26 and 1.27. How we verify. Unclear or wrong? Tell us