An unbuffered channel synchronizes sender and receiver — both must be ready simultaneously. A buffered channel decouples them up to the buffer capacity, after which the sender blocks.
Unbuffered: guaranteed handoff, synchronization points, request-reply patterns
Buffered: decouple producer and consumer speeds, absorb bursts, pipeline stages
Buffered channels are NOT a substitute for proper back-pressure — a full buffer that never drains causes goroutine leaks
Rule of thumb: start with unbuffered, add buffer only when profiling shows unnecessary blocking
Closing a channel signals no more values — receivers drain remaining buffered values before seeing the zero value