欢迎来到 Golang 系列教程[1]的第 24 篇。
什么是 select?
selectselectselectswitchcase
示例
package main
import (
"fmt"
"time"
)
func server1(ch chan string) {
time.Sleep(6 * time.Second)
ch "from server1"
}
func server2(ch chan string) {
time.Sleep(3 * time.Second)
ch "from server2"
}
func main() {
output1 := make(chan string)
output2 := make(chan string)
go server1(output1)
go server2(output2)
select {
case s1 := fmt.Println(s1)
case s2 := fmt.Println(s2)
}
}
在线运行程序[2]
server1from server1chserver2from server2ch
mainserver1server2
selectselectserver1output1server2output2selectserver2output2
from server2
然后程序终止。
select 的应用
server1server2select
server1server2selectselect
默认情况
selectselect
package main
import (
"fmt"
"time"
)
func process(ch chan string) {
time.Sleep(10500 * time.Millisecond)
ch "process successful"
}
func main() {
ch := make(chan string)
go process(ch)
for {
time.Sleep(1000 * time.Millisecond)
select {
case v := fmt.Println("received value: ", v)
return
default:
fmt.Println("no value received")
}
}
}
在线运行程序[3]
processprocess successfulch
processprocesschselectcase v := )并未就绪。所以在这期间,程序会执行默认情况,该程序会打印 10 次 no value received。no value received
processchprocess successfulselectreceived value: process successful
no value received
no value received
no value received
no value received
no value received
no value received
no value received
no value received
no value received
no value received
received value: process successful
死锁与默认情况
package main
func main() {
ch := make(chan string)
select {
case }
}
在线运行程序[4]
chselectchselectpanic
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/sandbox416567824/main.go:6 +0x80
如果存在默认情况,就不会发生死锁,因为在没有其他 case 准备就绪时,会执行默认情况。我们用默认情况重写后,程序如下:
package main
import "fmt"
func main() {
ch := make(chan string)
select {
case default:
fmt.Println("default case executed")
}
}
在线运行程序[5]
以上程序会输出:
default case executed
selectnil
package main
import "fmt"
func main() {
var ch chan string
select {
case v := fmt.Println("received value", v)
default:
fmt.Println("default case executed")
}
}
在线运行程序[6]
chnilselectchselectselect
default case executed
随机选取
select
package main
import (
"fmt"
"time"
)
func server1(ch chan string) {
ch "from server1"
}
func server2(ch chan string) {
ch "from server2"
}
func main() {
output1 := make(chan string)
output2 := make(chan string)
go server1(output1)
go server2(output2)
time.Sleep(1 * time.Second)
select {
case s1 := fmt.Println(s1)
case s2 := fmt.Println(s2)
}
}
在线运行程序[7]
server1server2selectserver1from server1output1server2from server2output2selectfrom server1from server2
请在你的本地系统上运行这个程序,获得程序的随机结果。因为如果你在 playground 上在线运行的话,它的输出总是一样的,这是由于 playground 不具有随机性所造成的。
这下我懂了:空 select
package main
func main() {
select {}
}
在线运行程序[8]
你认为上面代码会输出什么?
select
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select (no cases)]:
main.main()
/tmp/sandbox299546399/main.go:4 +0x20
本教程到此结束。祝你愉快。
上一教程 - 缓冲信道和工作池
下一教程 - Mutex[9]
推荐阅读
Go 经典入门系列 23:缓冲信道和工作池