Go里面提供了一個(gè)關(guān)鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動(dòng)。
創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),德陽企業(yè)網(wǎng)站建設(shè),德陽品牌網(wǎng)站建設(shè),網(wǎng)站定制,德陽網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,德陽網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
select的用法與switch語言非常類似,由select開始一個(gè)新的選擇塊,每個(gè)選擇條件由case語句來描述。
與switch語句可以選擇任何可使用相等比較的條件相比,select有比較多的限制,其中最大的一條限制就是每個(gè)case語句里必須是一個(gè)IO操作,大致的結(jié)構(gòu)如下:
select {
case <-chan1:
// 如果chan1成功讀到數(shù)據(jù),則進(jìn)行該case處理語句
case chan2 <- 1:
// 如果成功向chan2寫入數(shù)據(jù),則進(jìn)行該case處理語句
default:
// 如果上面都沒有成功,則進(jìn)入default處理流程
}
在一個(gè)select語句中,Go語言會(huì)按順序從頭至尾評(píng)估每一個(gè)發(fā)送和接收的語句。
如果其中的任意一語句可以繼續(xù)執(zhí)行(即沒有被阻塞),那么就從那些可以執(zhí)行的語句中任意選擇一條來使用。
如果沒有任意一條語句可以執(zhí)行(即所有的通道都被阻塞),那么有兩種可能的情況:
l 如果給出了default語句,那么就會(huì)執(zhí)行default語句,同時(shí)程序的執(zhí)行會(huì)從select語句后的語句中恢復(fù)。
l 如果沒有default語句,那么select語句將被阻塞,直到至少有一個(gè)通信可以進(jìn)行下去。
示例代碼:
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)
}
運(yùn)行結(jié)果如下:
有時(shí)候會(huì)出現(xiàn)goroutine阻塞的情況,那么我們?nèi)绾伪苊庹麄€(gè)程序進(jìn)入阻塞的情況呢?我們可以利用select來設(shè)置超時(shí),通過如下的方式實(shí)現(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里面提供了一個(gè)關(guān)鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動(dòng)。
2)select的用法與switch語言非常類似,由select開始一個(gè)新的選擇塊,每個(gè)選擇條件由case語句來描述。
3)與switch語句可以選擇任何可使用相等比較的條件相比, select有比較多的限制,其中最大的一條限制就是每個(gè)case語句里必須是一個(gè)IO操作
*/
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x: //此處執(zhí)行了發(fā)送,如果成功向c寫入數(shù)據(jù),則進(jìn)行該case處理語句
x, y = y, x+y
case <-quit: //此處執(zhí)行了接收, 如果quit成功讀到數(shù)據(jù),則進(jìn)行該case處理語句
//從輸出結(jié)果可以看到, 此代碼一直不斷地向channel中寫入數(shù)據(jù)。 在main函數(shù)中只是讀取6個(gè)數(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設(shè)置超時(shí)
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當(dāng)前時(shí)間
fmt.Println("timeout")
o <- true
break
}
}
}()
//c <-666 //注釋掉,引發(fā)timeout
<-o
}