I think the accepted answer did not go into the exact reasons why.
The go language belongs to the procedural paradigm, meaning that every instruction is executed linearly. When a go routine is forked from the main go routine, it goes off on its own little adventure, leaving the main thread to return.
The buffered channel has a capacity of 5, which means it will not block until the buffer is full. It will also block if it is empty (a channel with zero capacity is inherently unbuffered).
Since there are only 4 iterations (0 to <=3), the read operation will not block.
By instructing the main thread to read from the done channel, we're forcing the main thread to wait until there is some data to be consumed in the done channel. When the iteration is over, the else branch is executed and the write operation done <- true
causes the release of the <- done
read operation in the main thread. The read operation waits to pull the now inserted value off of done
.
After reading from done
, the main Go routine is no longer blocked, hence terminating successfully.