Is there any difference between switch and select in Go,
apart from the fact that one takes an argument and the other not?
3 Answers
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." 1 Comment
switch explanation. It's not simply restricted to concrete types. By default, it does an equality check, and with no argument, each case statement must be a boolean expression, with the first true case being chosen.switch
switch is used to make a decision based on a variable value of any type. Read this for more details:
Go's
switchis 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 theswitchhas 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) } } } 1 Comment
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:
selectworks just on channel events (receive, close or wait), but you can useswitchjust for comparing channel data likecase <-ch == 1:switchworks in deterministic way like multipleiforif elsestatement, butselectchooses thecasein non-deterministic way: you can't say which case runs first inselect- you can't use
fallthroughinselect - in
switchAn expression or type specifier is compared to thecasesinside theswitchto determine which branch to execute. switchis not blocking itself, butselectis blocking underlying goroutine unless you usedefaultswitchhas two forms: expression switches and type switches- in blocking
select(withoutdefault) there is no CPU usage (goroutine sleep) - Unlike
selectyou can't usecase <-ch:insideswitch.
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