go:goroutine與channel
goroutine:可以理解為一個輕量的執行緒,語法:go 函式名()
channel:中文為“通道”,可以理解為一個管,一端進行接資料,另一端收資料。語法:c:=make(chan int)。通道需要有接收和傳送。
關於goroutine與channel的組合使用,見如下2個例子。
例1:channel通訊
1 func sum(a int,c chan int){ 2 num:=a+100 3 c <- num 4 } 5 6 func main(){ 7 c:=make(chan int) 8 go sum(100,c) 9 sum1:= <- c 10 fmt.Println(sum) 11 }
輸出:>>>200
備註:
a.這段程式碼寫了2個函式,sum()與main()通過channel通訊,並且在main中使用goroutine開啟一個執行緒。
b.sum()函式的引數有一個int和一個channel,且在第3行將函式的執行結果使用channel接收。在mian()函式中,channel的資料傳送給變數sum1,以此實現channel通訊的作用。
c.在第8行,通過go開始了一個協程,如果去掉go就相當於沒有開啟協程,會出現dead lock。或者修改第7行第8行如下:
... c:=make(chan int,1) sum1(100,c) ...
修改後的c在make時就定義了一個緩衝區,緩衝區的大小為1,緩衝區可以理解為佇列長度。執行時超出佇列長度也會報錯。
例2:channel的通知作用
1 var complete chan int =make(chan int) 2 3 func loop(){ 4 for i:=0;i<10;i++{ 5 fmt.Printf("%d \t",i) 6 } 7 complete <- 0 8 } 9 10 func main(){ 11 go loop()12 // loop() 13 <- complete
結果:>>>0 1 2 3 4 5 6 7 8 9
備註:
a.這段程式碼主要是描述channel的通知作用:main函式的 <- complete 其實就是阻塞住main線不讓main線過早跑完,直到main線從complete中讀出訊息(0)
b.第11行和第12行,loop()被呼叫2次,第一次是roroutine開啟的執行緒,第二次是main()開啟的。而main()退出比較快,它執行完了goroutine還未來得及執行。或者可以在12行後加一個延遲(time.Sleep(time.Second)),加了之後兩個執行緒都可以執行、
c.第7行體現了channel的通知作用:當loop()函式體執行完畢後,會發訊息給channel,訊息是0;在第13行,如果取到了訊息(0)則說明goroutine的執行緒跑完了,否則mian()會阻塞住。