Closing channels

The best way of handling the end of a synchronization between a sender and a receiver is the close operation. This function is normally executed by the sender because the receiver can verify whether the channel is still open each time it gets a value using a second variable:

value, ok := <-ch

The second receiver is a Boolean that will be true if the channel is still open, and false otherwise. When a receive operation is done on a close channel, the second received variable will have the false value, and the first one will have the 0 value of the channel type, such as these:

The example of sending multiple messages can be rewritten using the close function, without having prior knowledge of how many messages will be sent:

func main() {
const max = 10
var a = make(chan int)

go func() {
for i := 0; i < max; i++ {
a <- i
}
close(a)
}()
for {
v, ok := <-a
if !ok {
break
}
fmt.Println(v)
}
}

The full example is available at https://play.golang.org/p/GUzgG4kf5ta.

There is a more synthetic and elegant way to receive a message from a channel until it's closed: by using the same keyword that we used to iterate maps, arrays, and slices. This is done through range:

for v := range a {
fmt.Println(v)
}