Причина, по которой вам, возможно, понадобится истощить канал, заключается в том, как запланированы горутины.
Проблема
Представьте себе этот случай:
- Создан таймер
- Таймер срабатывает, отправляя значение на
t.C
- Ничто еще не получило / не прочитало значение, но вызывается
t.Stop()
.
В этом случае на канале есть значение t.C
, и t.Stop()
возвращает значение false, поскольку «таймер уже истек» (т. Е. Когда он отправил значение на t.C
).
Причина, по которой в документах говорится, что «это нельзя сделать одновременно с другими получателями», заключается в том, что нет гарантии порядка между if !t.Stop {
и <-t.C
. Команда stop может вернуть false, введя тело if. И тогда можно было бы запланировать другую процедуру и прочитать значение из t.C
, которое пыталось истощить в теле оператора if. Это приведет к возникновению данных и блокированию внутри оператора if. (как вы указали в своем вопросе!)
Решение
Это зависит от поведения слушающей таймер вещи.
Если вы просто выберите:
select {
case result <- doWork():
case <-t.C
}
Нечто подобное выше. Может произойти одно из нескольких:
- Работу можно было бы сделать с
doWork
, отправив результат, все хорошо.
- Таймер может срабатывать, вызывая тайм-аут и прерывая выбор.
- Вызов, чтобы остановить, остановить таймер, единственный выход из выбора -
doWork()
завершение.
- Таймер может сработать, другие обычные вызовы
t.Stop()
, но это слишком
поздно, потому что значение было отправлено, вызывая тайм-аут, разрыв
выбор.
Пока вы в порядке с делом 4, вам не нужно взаимодействовать / истощать канал после вызова Stop.
Если вы не в порядке с делом 4. Вы по-прежнему не можете использовать канал t.C
, потому что его слушает другая программа. Это может заблокировать в операторе if. Вместо этого вы должны найти другой способ выложить код или убедиться, что ваша программа в списке выбора все еще не прослушивает канал.