Go-Select

Go里面的一個關(guān)鍵字,用于監(jiān)聽channel上的數(shù)據(jù)流動。select語句里面的每條case語句必須是一個IO操作。

select {
case <- chan1;
        //如果chan1成功讀 取到數(shù)據(jù),則進(jìn)行該case語句處理。
case chan2 <- 1;
        //如果成功向chan2中寫入數(shù)據(jù),則進(jìn)行case語句處理。
default;
        //如果上面都沒有成功,則進(jìn)入default語句處理,通常不用(會產(chǎn)生忙輪訓(xùn))
}

代碼示例:

package main
import (
    "fmt"
    "runtime"
    "time"
)
func main () {
    //定義兩個channel
    ch := make(chan int)//用于通信
    quit := make(chan bool)//用于判斷是否退出
    //新建一個子goroutine,用于channel寫
    go func() {
        for i :=0; i < 5; i++ {
            ch <- i
            time.Sleep(time.Second)
        }
        close(ch)//關(guān)閉channel
        quit <- true//通知主goroutine是否退出
        runtime.Goexit()
    }()
    //主goroutine用于讀取
    for  {
        select {
        case  num := <- ch :
            fmt.Println("讀到:",num)
        case  <- quit:
            return
        }
        fmt.Println("###############")
    }
}

輸出:

讀到: 0
###############
讀到: 1
###############
讀到: 2
###############
讀到: 3
###############
讀到: 4
###############

斐波那契數(shù)列:

package main
import (
    "fmt"
    "runtime"
)
//打印輸出Fibonacci
func fibonacci (ch <- chan int,quit <- chan bool)  {
    for {
        select {
        case num :=  <- ch://從管道中讀取數(shù)據(jù)
            fmt.Print(num," ")
        case <- quit:
            runtime.Goexit()//退出子goroutine
        }
    }
}
func main () {
    //定義兩個channel
    ch := make(chan int)//用于通信
    quit := make(chan bool)//用于判斷主goroutine是否退出
    go fibonacci(ch,quit)//打印輸出Fibonacci
    //主goroutine用于計算
    x,y := 1,1
    for i := 0; i < 20; i++ {
        ch <- x
        x, y = y, x + y
    }
    quit <- true
}

注意事項:
1、監(jiān)聽的case中,沒有滿足的監(jiān)聽條件,阻塞。
2、監(jiān)聽的case中,有多個滿足監(jiān)聽條件,任選一個執(zhí)行。
3、可以使用default來處理所有的case都不滿足的條件的狀況,通常不用(會產(chǎn)生忙輪訓(xùn))。
4、select自身不帶有循環(huán)機(jī)制,需要借助外層的for循環(huán)來監(jiān)聽。
5、break只能跳出select,類似于switch中的用法。不能使用break跳出主goroutine,如果要跳 出子goroutine,可以使用runtime.Goexit()

超時:

package main
import (
    "fmt"
    "time"
)
func main () {
    ch := make(chan int)
    quit := make(chan bool)
    //timer := time.NewTimer(time.Second*3)
    go func() {
        for {
            select {
            case num := <- ch: //這里阻塞了,因?yàn)闆]有寫
            fmt.Println("num=",num)
            //case <- timer.C: //等待3秒后,把系統(tǒng)時間讀取出來
            case <- time.After(3*time.Second)://等待3秒后,把系統(tǒng)時間讀取出來
                fmt.Println("超時")
                 quit <- true//判斷是否退出
                 break
            }
        }
    }()

     <- quit//主goroutine從管道中讀取
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容