Go語言中的管道(Channel)總結


管道(Channel)是Go語言中比較重要的部分,經常在Go中的並發中使用。今天嘗試對Go語言的管道來做以下總結。總結的形式采用問答式的方法,讓答案更有目的性。

Q1.管道是什么?
管道是Go語言在語言級別上提供的goroutine間的**通訊方式**,我們可以使用channel在多個goroutine之間傳遞消息。channel是**進程內**的通訊方式,是不支持跨進程通信的,如果需要進程間通訊的話,可以使用Socket等網絡方式。

以上是管道的概念,下面我們就看下管道的語法。

Q2.管道的語法?

整個Go語言的語法都比較簡潔,管道也不例外,其語法如下所示:

在此應當注意,管道是類型相關的,即一個管道只能傳遞一種類型的值。管道中的數據是先進先出的。

 1 // 聲明方式,在此ElemType是指此管道所傳遞的類型
 2 var chanName chan ElemType
 3 // 聲明一個傳遞類型為int的管道
 4 var ch chan int
 5 // 聲明一個map,元素是bool型的channel
 6 var m map[string] chan bool
 7 
 8 // 定義語法,定義需要使用內置函數make()即可,下面這行代碼是聲明+定義一個整型管道
 9 ch := make(chan int)
10 // 事先定義好管道的size,下面這行代碼定義管道的size為100
11 ch := make(chan int, 100)
12 
13 // 由管道中讀寫數據,<-操作符是與最左邊的chan優先結合的
14 // 向管道中寫入一個數據,在此需要注意:向管道中寫入數據通常會導致程序阻塞,直到有
15 // 其他goroutine從這個管道中讀取數據
16 ch<- value
17 // 讀取數據,注意:如果管道中沒有數據,那么從管道中讀取數據會導致程序阻塞,直到有數據
18 value := <-ch
19 
20 // 單向管道
21 var ch1 chan<- float64     // 只能向里面寫入float64的數據,不能讀取
22 var ch2 <-chan int         // 只能讀取int型數據
23 
24 // 關閉channel,直接調用close()即可
25 close(ch)
26 // 判斷ch是否關閉,判斷ok的值,如果是false,則說明已經關閉(關閉的話讀取是不會阻塞的)
27 x, ok := <-ch

 

 

Q3.管道的使用場景?

在第一個問題中,我們已經知道管道可以做進程間通訊,Go中自帶了對協程的支持(關鍵字go),而管道就是各個協程間通訊的一個方法。這里我們舉些簡單的小例子來說明一下管道如何在協程中使用。

 1 package main
 2 import "fmt"
 3 
 4 func print() {
 5     fmt.Println("Hello world")
 6 }
 7 
 8 func main() {
 9     for i := 0; i < 10; i++ {
10         go print()
11     }
12 }

 


上面的代碼意思大致是:使用協程來並行輸出10次 "Hello world", 但是大家運行上面代碼的時候,會發現不會有輸出。這是因為雖然使用go關鍵字進行了協程的創建,但是還沒有等到執行的時候,main函數已經退出來了,進程已經關閉,所以起來的協程也不會被執行。

如果你有C相關的多線程經驗時,可已經將協程改為線程,之后調用線程的join方法,讓主線程等待子線程執行完畢后再退出。而在Go語言中,我們可以利用管道的寫入阻塞和讀取阻塞來完成類似線程join的行為。代碼如下所示:

 1 package main
 2 import "fmt"
 3 
 4 func print(ch chan int) {
 5     fmt.Println("Hello world")
 6     ch<- 1
 7 }
 8 
 9 func main() {
10     chs := make([]chan int)
11     for i := 0; i < 10; i++ {
12         chs[i] = make(chan int)
13         go print(chs[i])
14     }
15     
16     for _, ch := range(chs){
17         <-ch
18     }
19 }

通過以上代碼,我們就可以完成了並行輸出10此Hello world 的效果。

有一個問題留給大家,如果將 print改為

1 func print(ch chan int){
2     ch<- 1
3     fmt.Println("Hello world")
4 }

 

會打印出什么呢?

由於水平有限,難免會有錯誤,請大家指正。
謝謝。
[3/30]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM