Если вы намеренно не добавите точку блокировки в основной поток, программа остановит выполнение до того, как получатель напечатает последний элемент.Это работа, выполняемая объектом WaitGroup
и вызовом WaitGroup.Wait()
.
При этом вы сообщаете основному потоку, что одновременно выполняется другая операция и что вы хотите дождаться ее завершения, прежде чем завершить выполнение вашей программы.Об этом будет сообщено с помощью оператора wg.Done()
.
Однако в этом случае это необходимо только потому, что в противном случае получатель не смог бы получить последний элемент до завершения выполнения в главном потоке.Но по большей части каналы также являются абстракцией синхронизации, и они диктуют ход выполнения программы.
Но обо всем по порядку, причина, по которой WaitGroup
не являетсядобавление в цикл связано с тем, что в вашей программе есть только одна точка, которую вы обязательно хотите ждать.Одна процедура, состоящая из одного канала.
Поскольку в данном примере мы работаем с каналом Unbuffered
, он позволяет передавать по каналу только 1 сообщение за один раз. Это означает, что для каждого сообщения, отправленного передатчиком, передатчик будет заблокирован до тех пор, пока получатель не извлечет такое сообщение и не удалит его из канала.
Когда передатчик отправит последний элемент,он закроет канал, указывая получателю, что больше сообщений не будет приниматься позже.Итерация, происходящая с range ch
, прекратит работу после получения «10», и выполнение goroutine
окончательно прервет выполнение цикла.
Вот что происходит:
// Передатчик отправляет "1"
// Передатчик теперь заблокирован, так как канал unbuffered
.
// Receiver получает "1"
// Receiver теперь блокируется, пока что-то не передается на канал.
// Передатчик теперь разблокирован и может передавать снова.
// .....
// Передатчик отправляет "10"
// Приемник получил "10"
После этого функция goможет, наконец, вычесть счетчик на WaitGroup
, вызвав его статический метод Done
, и счетчик достигнет нуля, что означает, что операция блока, происходящая из-за wg.Wait()
, прекратит свое существование, и основной поток может наконец достичьзавершение и прекращение выполнения программы.
Ключевые моменты:
-
channel
, который мы используем для канала unbuffered
, что означает 1 сообщение за раз.С другой стороны, с буферизованными каналами вы можете одновременно передавать несколько сообщений, прежде чем получатель действительно решит их получить, и преимущества WaitGroup
могут стать намного более очевидными. - с
<- i
, вы отправляете что-то на channel
, а с range ch
вы получаете такие сообщения.Передаваемые сообщения имеют фиксированный тип переменной, в данном случае целое число.