Результат, возвращаемый здесь true, является детерминированным в этом сценарии, это не случайный результат, полученный средой выполнения, потому что доступно только истинное значение (сколько бы времени оно ни потребовалось, чтобы оно стало доступным!), Отправляемое в канал, ложный результат никогда не будет доступен для канала с момента вызова time.After () никогда не получит шанс быть выполнен в первую очередь!
В этом select первая исполняемая строка, которую он видит, это вызов check (u), а не канал, отправляющий вызов в первой ветви case, или любой другой вызов вообще! И только после того, как это первое выполнение check (u) вернется сюда, выберет варианты ветвления, которые будут проверены и вызваны, к этому моменту значение true уже будет помещено в первый канал варианта ветвления, поэтому здесь нет блокировки канала к оператору select, здесь select может быстро выполнить свою задачу без необходимости проверять оставшиеся варианты ветвления!
так что похоже, что использование здесь select было бы не совсем правильным в этом сценарии.
Предполагается, что выбранные варианты ветвления непосредственно прослушивают отправку и получение значений канала или, необязательно, со значением по умолчанию, чтобы избежать блокировки, когда это необходимо.
так что исправление, как уже указывали здесь некоторые люди, помещает длительную задачу или процесс в отдельную горутину и отправляет результат в канал, а затем в основную горутину (или любую другую процедуру, которая требует это значение вне канала ), используйте варианты ветвления select для прослушивания значения на этом конкретном канале или на канале, предоставленном вызовом time.After (time.Second).
По сути, эта строка: case ch ‹- check (u) верна в смысле отправки значения в канал, но это просто не для его предполагаемого использования (т.е. блокирование этого случая ветвления), потому что case channel‹ - не быть заблокированным там вообще (время, затрачиваемое на проверку (u), происходит до того, как будет задействован канал), поскольку в отдельной горутине, также известной как основная: return ‹-ch, она уже готова прочитать это значение всякий раз, когда оно проталкивается. Вот почему оператор вызова time.After () во второй ветке case никогда даже не получит шанса быть вычисленным в первом экземпляре!
см. этот пример для простого решения, т.е. правильное использование select в сочетании с отдельными горутинами: https://gobyexample.com/timeouts
person
xman
schedule
31.08.2019