通道(channel)是go語言中一種非常獨特的資料結構。它可用於在不同goroutine之間傳遞型別化的資料,並且是併發安全的。相比之下,我們之前介紹的那些資料型別都不是併發安全的。這一點需要特別注意。
goroutine(也稱為go程式)可以被看做是承載可被併發執行的**塊的載體。它們由go語言的執行時系統排程,並依託作業系統執行緒(又稱核心執行緒)來併發地執行其中的**塊。至於怎樣編寫這樣的**塊以及怎樣驅動這樣的**塊執行,我們先按下不表。
通道型別的表示方法很簡單,僅由兩部分組成,如下:
chan t在這個型別字面量中,左邊是代表通道型別的關鍵字
chan
,而右邊則是乙個可變的部分,即代表該通道型別允許傳遞的資料的型別(或稱通道的元素型別)。這兩部分之間需要以空格分隔。
與其它的資料型別不同,我們無法表示乙個通道型別的值。因此,我們也無法用字面量來為通道型別的變數賦值。我們只能通過呼叫內建函式make
來達到目的。make
函式可接受兩個引數。第乙個引數是代表了將被初始化的值的型別的字面量(比如chan int
),而第二個引數則是值的長度。例如,若我們想要初始化乙個長度為5
且元素型別為int
的通道值,則需要這樣寫:
make(chan int, 5)順便說一句,實際上
make
函式也可以被用來初始化切片型別或字典型別的值。
確切地說,通道值的長度應該被稱為其快取的尺寸。換句話說,它代表著通道值中可以暫存的資料的個數。注意,暫存在通道值中的資料是先進先出的,即:越早被放入(或稱傳送)到通道值的資料會越先被取出(或稱接收)。
下面,我們宣告乙個通道型別的變數,並為其賦值:
ch1 := make(chan string, 5)這樣一來,我們就可以使用接收操作符
<-
向通道值傳送資料了。當然,也可以使用它從通道值接收資料。例如,如果我們要向通道ch1
傳送字串"value1"
,那麼應該這樣做:
ch1 <- "value1"另一方面,我們若想從
ch1
那裡接收字串,則要這樣:
<- ch1這時,我們可以直接把接收到的字串賦給乙個變數,如:
value := <- ch1與針對字典值的索引表示式一樣,針對通道值的接收操作也可以有第二個結果值。請看下面的示例:
value, ok := <- ch1
這樣做的目的同樣是為了消除與零值有關的歧義。這裡的變數ok
的值同樣是bool
型別的。它代表了通道值的狀態,true
代表通道值有效,而false
則代表通道值已無效(或稱已關閉)。更深層次的原因是,如果在接收操作進行之前或過程中通道值被關閉了,則接收操作會立即結束並返回乙個該通道值的元素型別的零值。按照上面的第一種寫法,我們無從判斷接收到零值的原因是什麼。不過,有了第二個結果值之後,這種判斷就好做了。
說到關閉通道值,我們可以通過呼叫內建函式close
來達到目的,就像這樣:
close(ch1)請注意,對通道值的重複關閉會引發執行時恐慌。這會使程式崩潰。所以一定要避免這種情況的發生。另外,在通道值有效的前提下,針對它的傳送操作會在通道值已滿(其中快取的資料的個數已等於它的長度)時被阻塞。而向乙個已被關閉的通道值傳送資料會引發執行時恐慌。另一方面,針對有效通道值的接收操作會在它已空(其中沒有快取任何資料)時被阻塞。除此之外,還有幾條與通道的傳送和接收操作有關的規則。不過在這裡我們記住上面這三條就可以了。
最後,與切片和字典型別相同,通道型別屬於引用型別。它的零值即為nil
。
go 通道 go語言通道channel
通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,他有點像在兩個routine之間架設的管道,乙個goroutine可以往這個管道裡塞資料,另外乙個可以從這個管道裡取資料,有點類似於我們說的佇列。宣告乙個通道很簡單,我們使用chan關鍵字即可,除此之外,還要指定通...
go語言通道插入0 Go 語言通道
51reboot 運維開發 golang 課程 k8s 課程 python 自動化高階課程 python 基礎實戰課程 運維前端課程 課程試聽預約請掃碼 原子函式和互斥函式都能工作,但是依靠它們都不會讓編寫併發程式變得更簡單,更不容易出錯,或者更有趣。在 go 語言裡,你可以使用通道來傳送和接收需要...
go語言通道插入0 Go語言之通道
所以在多個goroutine併發中,我們不僅可以通過原子函式和互斥鎖保證對共享資源的安全訪問,消除競爭的狀態,還可以通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,它有點像在兩個routine之間架設的管道 乙個goroutine可以往這個管道裡塞資料,另外乙個...