Channels are one of the selling points of the language Go. The logic of whether the reading of writing operation on a channel is blocking depends on a number of factors. This article summaries common scenarios.

Operation Closed channel Drained channel Saturated channel
Write to channel: c <- 3 panic: send on closed channel Proceeds immediately Blocks until other goroutine reads from channel
Read from channel: <-c Proceeds immediately, receives nil value Blocks until other goroutine writes to channel Proceeds immediately, receives value from channel
Read in select without default
select {
  case x := <- ch1:
    // use x
}
Reads from channel case with nil value Blocks until other goroutine writes to channel Reads from channel case
Read in select with default
select {
  case x := <- ch1:
    // use x
  default:
}
Reads from channel case with nil value Executes default case Reads from channel case