Go Select 详解
select语句让多个channel操作等待
Go的select语句让程序线程在多个channel的操作上等待,select语句在goroutine 和channel结合的操作中发挥着关键的作用。介绍一个小程序,演示这个select功能。
这个程序模拟接受消息功能,有两个channel接受发送过来的消息。select语句用来接受两个某个消息,for循环表示仅接受3个消息。
package main
import (
"time"
"log"
"strconv"
)
func receiveMsg(){
c1 := make(chan string)
c2 := make(chan string)
t1 := time.Now() // get current time
go func(){
//received three message
for i:=0; i < 3; i++ {
time.Sleep(time.Millisecond * 150)
c1 <- "msg 1 with index " + strconv.Itoa(i)
}
}()
go func(){
for j:=0; j < 3; j++ {
time.Sleep(time.Millisecond * 200)
c2 <- "msg 2 with index "+ strconv.Itoa(j)
}
}()
//print two message
for i:= 0; i < 3; i++ {
select {
case msg1 := <- c1:
log.Println("received msg :", msg1)
case msg2 := <- c2:
log.Println("received msg :", msg2)
}
}
elapsed := time.Since(t1)
log.Println("time elapsed ", elapsed)
}
func main() {
receiveMsg()
}
输出结果:
2017/02/16 10:55:51 received msg : msg 1 with index 0
2017/02/16 10:55:51 received msg : msg 2 with index 0
2017/02/16 10:55:51 received msg : msg 1 with index 1
2017/02/16 10:55:51 time elapsed 300.03ms
从结果来看,总时间为300多ms,goroutine并发执行对应的休眠时间后,select语句顺利获取对应消息,并打印消息日志。
select随机选择操作
select可以让多个交流操作等待,结合for永久循环,select保证它的case之一能够执行前发生阻塞。 当多个操作都准备好时,select随机选择一个case执行。
下面将介绍一个小程序,演示select的这个功能。
package main
import (
"log"
"fmt"
)
func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func exeFibonacci(){
c := make(chan int)
quit := make(chan int)
//produce data
go func(){
for i:= 0; i < 10; i++ {
log.Println("channel data item ", <- c)
}
quit <- 0
}()
fibonacci(c, quit)
}
func main() {
exeFibonacci()
}
输出结果:
2017/02/16 11:35:49 channel data item 0
2017/02/16 11:35:49 channel data item 1
2017/02/16 11:35:49 channel data item 1
2017/02/16 11:35:49 channel data item 2
2017/02/16 11:35:49 channel data item 3
2017/02/16 11:35:49 channel data item 5
2017/02/16 11:35:49 channel data item 8
2017/02/16 11:35:49 channel data item 13
2017/02/16 11:35:49 channel data item 21
2017/02/16 11:35:49 channel data item 34
quit
channel中的每个数字即为fibonacci值(select语句中的x变量值)。
default
select的default语句与Java中的switch一样,表示默认情况下的执行case。下面的例子介绍了具体的使用情况。
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.Print(".")
time.Sleep(50 * time.Millisecond)
}
}
}
运行结果:
..tick.
..tick.
..tick.
..tick.
..BOOM!
欢迎订阅微信公众号