Synchronous and Asynchronous Communication

This lesson describes synchronous and asynchronous communication and how channels are designed to handle both.

Blocking of goroutines

By default, communication is synchronous, and unbuffered, which means the send operation does not complete until there is a receiver to accept the value. One can think of an unbuffered channel as if there is no space in the channel for data. There must be a receiver ready to receive data from the channel, and then the sender can hand it over directly to the receiver. So, channel send/receive operations block until the other side is ready:

  • A send operation on a channel (and the goroutine or function that contains it) blocks until a receiver is available for the same channel ch. If there’s no recipient for the value on ch, no other value can be put in the channel, which means no new value can be sent in ch when the channel is not empty. So, the send operation will wait until ch becomes available again. This is the case when the channel-value is received (can be put in a variable).
  • A receive operation for a channel blocks (and the goroutine or function that contains it) until a sender is available for the same channel. If there is no value in the channel, the receiver blocks. Although this seems a severe restriction, this offers a simple form of synchronizing and which works well in most practical situations.

This is illustrated in the following program, where the goroutine pump sends integers in an infinite loop on the channel. However, because there is no receiver, the only output is the number 0.

Get hands-on with 1200+ tech skills courses.