Утверждение "select" выбирает, какой из набора возможных операций отправки или получения будет продолжен. Это похоже на утверждние "switch", но со всеми случаями (cases), относящимися к операциям связи.
SelectStmt = "select" "{" { CommClause } "}" .
CommClause = CommCase ":" StatementList .
CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
RecvStmt = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
RecvExpr = Expression .
Случай (case) с RecvStmt может присвоить результат RecvExpr одной или двум переменным, которые могут быть объявлены с помощью краткого объявления переменных. RecvExpr должен быть (возможно заключенной в скобки) операцией приема. Может быть не более одного случая по умолчанию, и он может появиться в любом месте списка случаев (cases).
Исполнение утверждения "select" происходит в несколько этапов:
- Для всех случаев в утверждении операнды канала операций приема и выражения канала и правой части выражений утверждений отправки оцениваются ровно один раз в порядке исходного кода при входе в "select" утверждение. Результатом является набор каналов для приема или отправки и соответствующие значения для отправки. Любые побочные эффекты в этой оценке будут иметь место независимо от того, какая (если таковая имеется) операция связи выбрана для продолжения. Выражения в левой части RecvStmt с кратким объявлением или присваиванием переменной еще не оценены.
- Если одно или несколько сообщений может быть продолжено, выбирается одно, которое может продолжаться, посредством равномерного псевдослучайного выбора. В противном случае, если есть случай по умолчанию, этот случай выбирается. Если случай по умолчанию отсутствует, утверждение "select" блокируется до тех пор, пока не будет продолжено хотя бы одно из сообщений.
- Если выбранный случай не является случаем по умолчанию, выполняется соответствующая операция связи.
- Если выбранный случай представляет собой RecvStmt с коротким объявлением переменной или присваиванием, левые выражения оцениваются и присваивается полученное значение (или значения).
- Список выписок выбранного случая выполнен.
Поскольку обмен данными по нулевым каналам никогда не может быть продолжен, select только с нулевыми каналами и без случая по умолчанию блокируется навсегда.
var a []int
var c, c1, c2, c3, c4 chan int
var i1, i2 int
select {
case i1 = <-c1:
print("received ", i1, " from c1\n")
case c2 <- i2:
print("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // то же самое что и: i3, ok := <-c3
if ok {
print("received ", i3, " from c3\n")
} else {
print("c3 is closed\n")
}
case a[f()] = <-c4:
// то же самое что и:
// case t := <-c4
// a[f()] = t
default:
print("no communication\n")
}
for { // отправляет случайную последовательность битов в c
select {
case c <- 0: // примечание: нет утверждения, нет fallthrough ("провала" в следующий случай), нет сворачивания случаев
case c <- 1:
}
}
select {} // блокируется навсегда
Читайте также:
Комментариев нет:
Отправить комментарий