Go語言channel超時機制

前沿     

    go語言沒有提供直接的超時處理機制,所謂超時可以理解爲我們上網瀏覽一些網站時,如果一段時間之後不操作,就會需要重新登錄;那麼我們應該如何實現這一功能呢?這時就需要select來設置超時。

   雖然selecct機制不是專門爲超時而設計的,卻能很方便的解決超時問題,因爲select的特點是隻要其中一個case已經完成,程序就會繼續往下執行,而不會考慮其他的case的情況。

     超時機制本身雖然也會帶來一些問題,比如在運行比較快的機器或者高速的網絡上運行正常的程序,到了慢速的機器或者網絡上運行就會出現問題,從而出現結果不一致的現象,但從根本上來說解決死鎖的價值要遠大於所帶來的的問題。

   select的用法與swith語言非常類似,由select開始一個新的選擇塊,每個選擇條件由case語句來描述。

與switch語句相比,select有比較多的限制,其中最大的一條限制就是每個case語句裏必須是一個IO操作,大致結構如下:

select {

        case <-chan1:

        //如果chan1成功讀取到數據,則進行case處理語句

        case chan2<-1:

        //如果成功向chan2寫入數據則進行該case處理語句

        default:

        //如果上面的都沒有成功,則進入default處理流程

}

在一個select語句中,go語言會按照順序從頭至尾評估每一個發送和接收的語句。如果其中的任意一語句可以繼續執行(即沒有被阻塞),那麼就從那些可以執行的語句中任意選擇一條來使用。果沒有任意一條語句可以執行(即所有通道都被阻塞),那麼有如下兩種可能的情況:

  • 如果給出了default語句,那麼就會執行default語句,同時程序的執行會從select語句後的語句中恢復;
  • 如果沒有default語句,那麼select語句將被阻塞,直到至少有一個通信可以進行下去。

示例代碼:

package main

import (

        "fmt"

        "time"

)

func main() {

        ch := make(chan int)

        quit := make(chan bool)

        //新開的一個協程

        go func() {

                for {

                        select {

                        case num := <-ch:

                                fmt.Println("Num =", num)

                        case <-time.After(3 * time.Second):

                                fmt.Println("超時")

                                quit <- true

                        }

                }

        }() //別忘了()

        for i := 0; i < 5; i++ {

                ch <- i

                time.Sleep(time.Second)

        }

        <-quit

        fmt.Println("程序結束")

}

輸出結果:

Num = 0

Num = 1

Num = 2

Num = 3

Num = 4

超時

程序結束

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章