В чем разница между switch и select в Go?

есть ли разница между switch и select в Go,
помимо того, что один принимает аргумент, а другой нет?

3 ответов


A select используется только с каналами. пример

A switch использовано с конкретными типами. пример

A select будет выбирать несколько допустимых параметров наугад, в то время какswitch будет идти в последовательности(и потребует fallthrough, чтобы соответствовать нескольким.)

обратите внимание, что коммутатор также может переходить по типам интерфейсов при использовании с ключевым словом .(type)

var a interface{}
a = 5
switch a.(type) {
case int:
     fmt.Println("an int.")
case int32:
     fmt.Println("an int32.")
}
// in this case it will print "an int."

переключатель используется для принятия решения на основе значения переменной любого типа. Читать этой для получения более подробной информации:

переключатель Go более общий, чем C. Выражения не должны быть константами или даже целыми числами, случаи вычисляются сверху вниз до тех пор, пока не будет найдено совпадение, и если переключатель не имеет выражения, он включает true. Поэтому возможно-и идиоматично-написать цепочку "если-еще-если-еще" в качестве переключателя.

Пример Использования: ( Go Playground)

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Print("Go runs on ")
    switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        // freebsd, openbsd,
        // plan9, windows...
        fmt.Printf("%s.", os)
    }
}

на выберите оператор позволяет goroutine ждать нескольких операций связи.

a select блокирует до тех пор, пока один из его случаев не сможет работать, затем он выполняет этот случай. Он выбирает один наугад, если несколько готовы. Вот один пример: ( Go Playground)

package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}

выберите заявления

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

переключатель заявления

операторы"Switch" обеспечивают многоходовое выполнение. Выражение или тип спецификатор сравнивается с" случаями " внутри "переключатель" для определения какую ветку выполнять. Существует две формы: Expression switches и переключатели типа. В коммутаторе выражений случаи содержат выражения которые сравниваются со значением выражения switch. В тип переключатель, случаи содержат типы, которые сравниваются с тип специально аннотированного выражения switch. Выражение переключателя оценивается только один раз в операторе switch.

Да, есть много различий:

  • select работает только на событиях канала (прием, закрытие или ожидание), но вы можете использовать switch просто для сравнения данных канал Как case <-ch == 1:
  • switch работает детерминированным образом, как несколько if или if else утверждение, но select выбирает case недетерминированным способом: вы не можете сказать, какой случай запускается первым в select
  • вы не можете использовать fallthrough на select
  • на switch спецификатор выражения или типа по сравнению с cases внутри switch чтобы определить, какую ветку выполнить.
  • switch не блокирует себя, но select блокирует базовый goroutine, если вы не используете default
  • switch имеет две формы: переключатели выражений и переключатели типов
  • в блокировании select (без default) нет использования процессора (goroutine sleep)
  • в отличие от select вы не можете использовать case <-ch: внутри switch.

рабочая пример кода:

package main

import "fmt"

func main() {
    ch := make(chan int, 4)
    ch <- 1
    ch <- 2
    ch <- 3
    ch <- 4
    close(ch)
    switch {
    //case <-ch: //  invalid case <-ch in switch (mismatched types int and bool)
    case <-ch == 1:
        fmt.Println("switch1")
        fallthrough
    case <-ch == 2:
        fmt.Println("switch2")
    }
    select {
    case d := <-ch:
        fmt.Println("select1 d=", d)
    case d := <-ch:
        fmt.Println("select2 d=", d)
    }
}

выход:

switch1
switch2
select2 d= 2

вывод еще раз:

switch1
switch2
select1 d= 2