select
заявление выполняется через его cases
(отправка/получение канала) один раз. Если ни один из его случаев не готов к выполнению, он блокируется, пока не будет выполнен хотя бы один из case
. Если одновременно запускается несколько случаев, один из готовых кейсов выбирается для случайного выполнения.
Таким образом, во втором случае, если есть некоторые данные на канале something
, он будет считан и помещен в s
. Но есть также шанс, что true
будет отправлен на done
, а case s := <-something:
никогда не будет выполнен.
В первом случае, вы, вероятно, хотите что-то вроде этого (и во втором случае):
for{
select{
case s := <-something:
fmt.Println(s)
case <-done: // note the difference
return
}
}
Что это сейчас делает то, что он ждет данных о something
, а также следит за done
. Если есть данные по каналу something
(и данных нет на done
), он будет считан и помещен в s
(регистр case case s := <-something:
будет выполнен с s
, имеющий значение, считанное с something
). Это будет учитывать одно полное выполнение инструкции select
, и элемент управления вернется в цикл for
, и он начнется снова.
Если нет данных по каналу something
, select
блоков и ожидает данных по обе something
или done
.Если данные поступают на something
, выполняется аналогичное выполнение, как описано выше, в противном случае, если оно поступило в done
, функция возвращает (выходит из цикла). Таким образом, какой-либо другой процесс может записать в done
и передать функцию, содержащую выше for
цикл, чтобы остановить обработку something
и вернуться.