Synchronization of goroutines

This lesson shows how closing or blocking a pattern, brings effective integration between goroutines.

Channels can be closed explicitly. However, they are not like files. You don’t usually need to close them. Closing a channel is only necessary when the receiver must be told that there are no more values coming. Only the sender should close a channel, never the receiver.

Closing a channel

The question is, how can we signal when sendData() is done with the channel, and how can getData() detect that the channel whether closed or blocked?

Signaling

This is done with the function close(ch). This marks the channel as unable to accept more values through a send operation <-. Sending to or closing a closed channel causes a run-time panic. It is good practice to do this with a defer statement immediately after the making of the channel (when it is appropriate in the given situation):

ch := make(chan float64)
defer close(ch)

Detection

This is done with the comma, ok operator. This tests whether the channel is closed and then returns true, otherwise false. How can we test that we can receive without blocking (or that channel ch is not closed)?

v, ok := <-ch // ok is true if v received a value

Often, this is used together with an if-statement:

if v, ok := <-ch; ok {
  ...
}

Or, when the receiving happens in a for loop, use break when ch is closed or blocked:

v, ok := <-ch
if !ok {
  break
}
// process(v)

We can trigger the behavior of a non-blocking send by writing: _ = ch <- v because the blank identifier takes whatever is sent on ch.

Get hands-on with 1200+ tech skills courses.