go學習筆記_Routine和Channel下

go語言併發編程下

上文從基礎層面講解了goroutinechannel ,關於如何使用都停留下嘴皮子上,因此下篇選用幾個最簡單的例子來鞏固下。另外推薦下自己的個人博客,你可以先點進行看下內容是否對您有幫助,在選擇收藏或者直接x掉。

個人博客地址:Colourful Code

正文

首先,上文說到channel 有兩種情況:

  • 未分配緩存

  • 分配一定緩存

例子從這兩點入手給出。

未分配緩存

package main
import "fmt"
//求和函數sum
func sum(a []int,c chan int){
    sum :=0
    for _,v := range a{
        sum += v
    }
    c<-sum          //向通道c 寫入數據值 sum
}
//主程序入口
func main(){
    a:= []int{1,3,5,2,-2}
    c:= make(chan int)
    go sum(a[:],c)      //開闢一個goroutine 用於進行sum函數執行
    x:= <-c             //讀取c通道的值賦值給x
    fmt.Println(x)
}

從主程序開始分析,如下分爲幾個步驟:

  • 聲明定義了一個數組 a

  • 聲明定義了一個通道 c,注意是沒有給定緩存的。

  • 正因爲加了go關鍵字 ,所以爲sum函數開闢一個goroutine,同時給函數傳入參數:數組a和通道c。這個時候程序除了主routine,也就是main函數。與此同時還有爲sum開闢的子routine,這個子routine所要做的就是對傳入的數組進行求和,並且將結果值寫入通道c中。

  • routine執行完go sum(a[:],c)這條語句之後,馬上就可以執行下一條語句了。也就是 x:=<-c。 這裏就有點意思了。要根據實際情況分2種情況來說:c 通道有值和無值。

    1. c 通道有值,這意味着子goroutine 中進行的求和運算先完成,通過語句c<-sum 將結果值寫入通道時,由於完成的太早,沒有接收方從通道讀取數據造成了堵塞,子routine中的程序卡死在這裏,等待接收者讀取數據。直到主routine執行了x:=<-c這條語句,順利的從通道讀取到了數據,於此同時子routinec<-sum 由於通道數據被讀走,這裏不再堵塞,子routine中的sum函數執行完畢。
    2. c 通道沒有值,意味着子goroutine 中進行的求和運算還未完成(假如這裏的求和運算改爲大數據處理,我想要花費很多時間。),數據還未寫入到c通道中,因此由於通道內沒有數據,主routine中會堵塞在 x:=<-c這條語句上,等待子routine完成數據計算,執行c<-sum語句往通道中寫數據。這時候主routine中 順利讀取通道c中的值,賦值給x,打印出來。

分配緩存

package main
import "fmt"
func main(){
    c:=make(chan int,2)
    c <- 10
    c <- 20
    fmt.Println(<-c)
    fmt.Println(<-c)
}

由於理解了channel 工作機制,那麼分配緩存理解起來容易一些。

  • 首先聲明定義一個緩存大小爲2的特定類型爲int的通道c

  • 往通道寫入值10,想一想,倘若沒有分配緩存,那麼程序會堵塞在這裏,除非其他routine會從該通道讀取數據,但這顯然不可能,因爲這時候是在主routine中,你又沒有創建子routine,所以最後只會報錯,“all goroutines are asleep - deadlock!”

  • 這時候你應該已經理解了,正因爲分配了緩存,因此能夠順利的寫入值10,接下來往通道寫入值20,顯然由於緩存還有空間,寫入沒有問題,不會造成堵塞,程序繼續執行下去!

  • <-c就是從通道中讀取數據,會打印10

  • 打印20,有種FIFO(注:“first in first out”,先入先出)的感覺,由於我們往通道緩存中寫入值10,再寫入值20,取出時就應該有順序的先取出值10,再取出值20。

結尾:

博主是一個剛入坑的go小菜鳥,對go語言理解可能還不是很透徹,倘若哪裏理解不對,或者寫的有問題,歡迎指正,踩踩更健康嘛,不過希望您能留言告訴我爲啥踩的理由嗎,好讓我改正,這也算一種學習不是嗎?最後謝謝!

發佈了75 篇原創文章 · 獲贊 70 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章