Go 中的 switch 和 select 有什么区别?

What is the difference between switch and select in Go?

围棋switchselect有区别吗,
除了一个争论另一个不争论的事实?

switch用于根据任意类型的变量值进行判断。阅读 this 了解更多详情:

Go's switch is more general than C's. The expressions need not be constants or even integers, the cases are evaluated top to bottom until a match is found, and if the switch has no expression it switches on true. It's therefore possible—and idiomatic—to write an if-else-if-else chain as a switch.

示例使用:(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)
    }
}

select 语句让 goroutine 等待多个通信操作。

A select 阻塞直到它的一个 case 可以 运行,然后它执行那个 case。如果多个准备就绪,它会随机选择一个。这是一个示例:(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)
        }
    }
}

A select 仅用于频道。 Example

A switch 与具体类型一起使用。 Example

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."

Select statements

A "select" statement chooses which of a set of possible send or receive operations will proceed. It looks similar to a "switch" statement but with the cases all referring to communication operations.

Switch statements

"Switch" statements provide multi-way execution. An expression or type specifier is compared to the "cases" inside the "switch" to determine which branch to execute. There are two forms: expression switches and type switches. In an expression switch, the cases contain expressions that are compared against the value of the switch expression. In a type switch, the cases contain types that are compared against the type of a specially annotated switch expression. The switch expression is evaluated exactly once in a switch statement.

是的,有很多区别:

  • select 仅适用于通道事件(接收、关闭或等待),但您可以使用 switch 仅用于比较通道数据,例如 case <-ch == 1:
  • switch 像多个 ifif else 语句一样以确定性方式工作,但 select 以非确定性方式选择 case :你可以不要说 select
  • 中第一个 运行 的情况
  • 您不能在 select
  • 中使用 fallthrough
  • in switch 将表达式或类型说明符与 switch 中的 cases 进行比较,以确定要执行的分支。
  • switch 不会阻塞自身,但是 select 会阻塞底层 goroutine,除非你使用 default
  • switch有两种形式:表达式开关和类型开关
  • 阻塞select(没有default)没有CPU使用(goroutine sleep)
  • select 不同,您不能在 switch 中使用 case <-ch:

工作示例代码:

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