Reputation: 8968
Is there any difference between switch
and select
in Go,
apart from the fact that one takes an argument and the other not?
Upvotes: 76
Views: 37981
Reputation: 8546
switch
switch
is used to make a decision based on a variable value of any type. Read this for more details:
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 theswitch
has no expression it switches ontrue
. It's therefore possible — and idiomatic — to write an if-else-if-else chain as aswitch
.
Sample Use: (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
The select
statement lets a goroutine wait on multiple communication operations.
A select
blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready. Here is one example: (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)
}
}
}
Upvotes: 48
Reputation: 7594
A select
is only used with channels. Example
A switch
is used with concrete types. Example
A select
will choose multiple valid options at random, while aswitch
will go in sequence (and would require a fallthrough to match multiple.)
Note that a switch can also go over types for interfaces when used with the keyword .(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."
Upvotes: 105
Reputation:
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 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.
Yes, there are many differences:
select
works just on channel events (receive, close or wait), but you can use switch
just for comparing channel data like case <-ch == 1:
switch
works in deterministic way like multiple if
or if else
statement, but select
chooses the case
in non-deterministic way: you can't say which case runs first in select
fallthrough
in select
switch
An expression or type specifier is compared to the cases
inside the switch
to determine which branch to execute.switch
is not blocking itself, but select
is blocking underlying goroutine unless you use default
switch
has two forms: expression switches and type switchesselect
(without default
) there is no CPU usage (goroutine sleep)select
you can't use case <-ch:
inside switch
.Working sample Code:
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)
}
}
output:
switch1
switch2
select2 d= 2
output of another run:
switch1
switch2
select1 d= 2
Upvotes: 11