Theme 1 – Blocking vs. Buffered Sends
Channels are unbuffered by default, so a send blocks until a receiver is ready; adding a buffer lets the goroutine proceed.
“channels are by default 'unbuffered', in that a send needs a waiting recv to actually do the send, and blocks until such. The addition of the buffer prevents the block & permits the goroutine to progress …” – deathanatos
Theme 2 – No Automatic Detection of Dead Receivers / Goroutine Lifetime
A channel does not notice when its receiver disappears, causing indefinite blocks; goroutines are not garbage‑collected and there is no join primitive.
“channels do not, AFAICT, realize when the receiver is gone, and will block indefinitely even when there is no receiver.” – deathanatos
“goroutines are not GC'd. (& the code doesn't/can't hold like, a reference or a handle to a goroutine / there is no 'join' primitive.)” – deathanatos
Theme 3 – Channel Closing Semantics and Idiomatic Use
Only the sender should close a channel; closing is often unnecessary and is used primarily for fan‑out patterns.
“(2) has a bit more nuance to it: you can close channels… but the langage is designed for that to be ok on single senders, a receiver can gracefully handle a closed channel … Aka go channels are designed for fan‑out.” – masklinn
“Channels aren't like files; you don't usually need to close them.” – masklinn