Оператор select

Оператор select позволяет горутине ожидать выполнения операций приема или отправки данных через каналы. Он выбирает первый канал, который готов к выполнению, и выполняет соответствующий блок кода. Если несколько каналов готовы одновременно, выбор происходит случайным образом. В первом параметре оператора мы передаем список операций с каналами для ожидания.

Синтаксис

goselect {
case <-chan1:
  // code
case chan2 <- value:
  // code
default:
  // code
}

Пример

Давайте создадим два канала и отправим данные в один из них, затем используем select для получения данных из первого готового канала:

gopackage main

import "fmt"

func main() {
  chan1 := make(chan string)
  chan2 := make(chan string)
  
  go func() {
    chan1 <- "first"
  }()
  
  go func() {
    chan2 <- "second"
  }()
  
  select {
  case res1 := <-chan1:
    fmt.Println(res1)
  case res2 := <-chan2:
    fmt.Println(res2)
  }
}

Результат выполнения кода:

go"first"

В зависимости от того, какая горутина первой отправит данные, результат может быть как "first", так и "second".

Пример

Рассмотрим использование select с блоком default, который выполняется, если ни один из каналов не готов к операции:

gopackage main

import "fmt"

func main() {
  chan1 := make(chan int)
  
  select {
  case res := <-chan1:
    fmt.Println(res)
  default:
    fmt.Println("No data received")
  }
}

Результат выполнения кода:

go"No data received"

Поскольку канал не содержит данных, выполняется блок default, и программа выводит соответствующее сообщение.

Пример

Используем select для отправки данных в канал, который готов принять значение:

gopackage main

import "fmt"

func main() {
  chan1 := make(chan string, 1)
  
  select {
  case chan1 <- "data":
    fmt.Println("Data sent successfully")
  default:
    fmt.Println("Channel is full")
  }
  
  fmt.Println(<-chan1)
}

Результат выполнения кода:

go"Data sent successfully"
"data"

Благодаря буферизированному каналу с емкостью 1 отправка данных выполняется успешно, после чего мы получаем отправленное значение.

Смотрите также

  • оператор select-default,
    который используется для неблокирующих операций с каналами
  • конструкцию go,
    которая запускает горутины для асинхронного выполнения функций
  • каналы chan,
    которые используются для обмена данными между горутинами
  • буферизированные каналы buffered-chan,
    которые позволяют хранить несколько значений без получателя