English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Обучающие курсы Golang

Управляющие операторы Golang

Функции и методы Golang

Структуры Golang

Срезы и массивы Golang

Строки (String) Golang

Указатели Golang

Интерфейсы Golang

Конкурентоспособность Golang

Исключения (Error) Golang

Другие的事项 Golang

Оператор Select языка Go

В языке Go заявление select подобноЗаявление switchНо в заявлении select случаи указывают на коммуникацию, то есть отправку или прием на канале.

Грамматика:

select{
case SendOrReceive1: // заявление
case SendOrReceive2: // заявление
case SendOrReceive3: // заявление
......
default: // заявление

Важные моменты:

  • Заявление select ждет готовности коммуникации (отправка или прием) для начала в некоторых случаях.

    package main
    import (
        "fmt"
        "time"
    )
    // функция 1
    func portal1(channel1 chan string) {
        time.Sleep(3 * time.Second)
        channel1 <- "Добро пожаловать на канал 1"
    }
    // функция 2
    func portal2(channel2 chan string) {
        time.Sleep(9 * time.Second)
        channel2 <- "Добро пожаловать на канал 2"
    }
    func main() {
        // создание канала
        R1 := make(chan string)
        R2 := make(chan string)
        // вызов функций 1 и 2 с помощью goroutine
        go portal1(R1)
        go portal2(R2)
        select {
        // case 1
        case op1 := <-R1:
            fmt.Println(op1)
        // case 2
        case op2 := <-R2:
            fmt.Println(op2)
        }
    }

    Вывод:

    Добро пожаловать в канал 1

    Объяснение использования:В предыдущем примере portal1 спит 3 секунды, portal2 спит 9 секунд, после окончания их времени сна они будут готовы продолжить. В настоящее время, заявление select ждет их время сна, когда portal2 проснется, он выберет case 2 и выведет "Добро пожаловать в канал 1". Если портал 1 проснется раньше, чем portal2, то выведется "Добро пожаловать в канал 2".

  • Если语句 select не содержит ни одного случая case, то это заявление select будет ждать вечно.

    Грамматика:

    select{}
    package main 
      
    func main() { 
          
       // не содержит ни одного case, будет ждать постоянно
       select{ } 
    }

    Вывод:

    фатальная ошибка: все goroutine спят - блокировка!
    goroutine 1 [select (no cases)]:
    main.main()
        /home/runner/main.go:9 +0x20
    exit status 2
  • default в предложении select используется для защиты select от блокировки. Когда ни один из case не готов, выполняется это предложение.

    package main
    import "fmt"
    func main() {
        // создание каналов
        mychannel := make(chan int)
        select {
        case <- mychannel:
        default:
            fmt.Println("Не найдено")
        }
    }

    Вывод:

    Не найдено
  • Блокировка select означает, что когда ни один из case не готов и select не содержит default, select будет блокироваться, пока не будет至少 одного case или сообщения, чтобы продолжить.

    package main
    func main() {
        // создание каналов
        mychannel := make(chan int)
        // канал еще не готов
        // и безdefault
        select {
        case <- mychannel:
        }
    }

    Вывод:

    фатальная ошибка: все goroutine спят - блокировка!
    goroutine 1 [chan receive]:
    main.main()
        /home/runner/main.go:14 +0x52
    exit status 2
  • В предложении select, если необходимо обработать несколько ситуаций, можно случайным образом выбрать одну из них.

    package main 
      
    import "fmt"
          
          
        // функция 1 
        func portal1(channel1 chan string){ 
            for i := 0; i <= 3; i++{ 
                channel1 <- "Добро пожаловать на канал 1"
            } 
              
        } 
          
        // функция 2 
         func portal2(channel2 chan string){ 
            channel2 <- "Добро пожаловать на канал 2"
        } 
      
    func main() { 
          
        // создание каналов 
       R1 := make(chan string) 
       R2 := make(chan string) 
         
       // использование goroutine для вызова функций 1 и 2
       go portal1(R1) 
       go portal2(R2) 
       
       // случайный выбор одного из них
       select{ 
           case op1 := <- R1: 
           fmt.Println(op1) 
           case op2 := <- R2: 
           fmt.Println(op2) 
       } 
    }

    Вывод:

    Добро пожаловать на канал 2