Обычное
v := <-ch из закрытого канала не заблокируется и не паникует, а сразу вернёт нулевое значение типа. Поэтому по одному
v нельзя отличить «пришёл реальный ноль» от «канал закрыт и пуст — ровно как с мапой:v := <-ch // 0 — но это может быть и настоящее значение, и признак закрытия
Второй параметр решает вопрос: флаг
ok равен true, пока из канала можно прочитать отправленное значение, и становится false, когда канал закрыт и в нём не осталось буферизованных данных. Важно, что закрытый канал сначала отдаёт всё, что в него успели записать, и только потом начинает возвращать
false:v, ok := <-ch
if !ok {
// канал закрыт и пуст
}
На практике за приёмом из канала обычно стоит
range, который сам корректно завершается при закрытии — отдельная проверка ok не нужна:for v := range ch {
// выполняется, пока канал не закрыт и не пустой
}