您好,登錄后才能下訂單哦!
Go里面提供了一個關鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動。
select的用法與switch語言非常類似,由select開始一個新的選擇塊,每個選擇條件由case語句來描述。
與switch語句可以選擇任何可使用相等比較的條件相比, select有比較多的限制,其中最大的一條限制就是每個case語句里必須是一個IO操作,大致的結構如下:
select {
case <-chan1:
// 如果chan1成功讀到數(shù)據(jù),則進行該case處理語句
case chan2 <- 1:
// 如果成功向chan2寫入數(shù)據(jù),則進行該case處理語句
default:
// 如果上面都沒有成功,則進入default處理流程
}
在一個select語句中,Go語言會按順序從頭至尾評估每一個發(fā)送和接收的語句。
如果其中的任意一語句可以繼續(xù)執(zhí)行(即沒有被阻塞),那么就從那些可以執(zhí)行的語句中任意選擇一條來使用。
如果沒有任意一條語句可以執(zhí)行(即所有的通道都被阻塞),那么有兩種可能的情況:
l 如果給出了default語句,那么就會執(zhí)行default語句,同時程序的執(zhí)行會從select語句后的語句中恢復。
l 如果沒有default語句,那么select語句將被阻塞,直到至少有一個通信可以進行下去。
示例代碼:
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 6; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
}
運行結果如下:
有時候會出現(xiàn)goroutine阻塞的情況,那么我們如何避免整個程序進入阻塞的情況呢?我們可以利用select來設置超時,通過如下的方式實現(xiàn):
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <-c:
fmt.Println(v)
case <-time.After(5 * time.Second):
fmt.Println("timeout")
o <- true
break
}
}
}()
//c <- 666 // 注釋掉,引發(fā) timeout
<-o
}
代碼如下所示:
// code_049_select_and_timeout project main.go
package main
import (
"fmt"
"time"
)
/*
1)Go里面提供了一個關鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動。
2)select的用法與switch語言非常類似,由select開始一個新的選擇塊,每個選擇條件由case語句來描述。
3)與switch語句可以選擇任何可使用相等比較的條件相比, select有比較多的限制,其中最大的一條限制就是每個case語句里必須是一個IO操作
*/
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x: //此處執(zhí)行了發(fā)送,如果成功向c寫入數(shù)據(jù),則進行該case處理語句
x, y = y, x+y
case <-quit: //此處執(zhí)行了接收, 如果quit成功讀到數(shù)據(jù),則進行該case處理語句
//從輸出結果可以看到, 此代碼一直不斷地向channel中寫入數(shù)據(jù)。 在main函數(shù)中只是讀取6個數(shù)據(jù), 而寫入的數(shù)據(jù)多于讀取的數(shù)據(jù)
fmt.Println("quit:y=", y)
return
}
}
}
func main() {
//1) select的使用
c1 := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 6; i++ {
fmt.Println(<-c1) //讀取數(shù)據(jù)
}
quit <- 0
}()
fibonacci(c1, quit)
//2) goroutine阻塞,利用select設置超時
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <-c:
fmt.Println(v)
case <-time.After(5 * time.Second): //返回值為channel類型,輸出值為Time當前時間
fmt.Println("timeout")
o <- true
break
}
}
}()
//c <-666 //注釋掉,引發(fā)timeout
<-o
}
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。