系統地回顧golang知識,今天總結一下channel的一些特點與一些簡單實現。
Don't communicate by sharing memory;share memory by communicating.
1,通道類型本身就是並發安全的,這也是go內建唯一可以滿足並發安全的類型。
2,通道需要初始化,因為其是參考型別,否則其值為nil,對其的任何操作都會阻塞。
3,可以理解為FIFO隊列,即便被阻塞的對象也是按照嚴格順序的,通道為空白,a協程取資料,然後b協程取資料,兩者都會阻塞,當通道有資料之後,仍然會遵循a與b的先後順序。
4,同一個通道的接收發送操作是互斥的,runtime同時只會執行一個通道的接收或者發送,不會同時進行。
5,對於通道中的元素也是,如果它還未完成被複製進通道,那麼其也絕不會被接收方所看到。
6,進入通道的並不是元素本身,而是元素的副本,並且這個操作是不會被割裂的,也就是說副本進入了通道,但原對象未被刪除。
7,同上,取出資料的時候也不會出現讀取後通道中的元素未被刪除的情況。
8,複製元素與將複製的副本放入通道之前,發送的操作會阻塞。
9,通道的阻塞機制是為了實現操作的互斥和元素的完成。
10,緩衝通道元素滿,接收與發送都會阻塞,但恢複後接收與發送的順序是絕對公平的,不會混亂。對於非緩衝通道,一開始就是阻塞的,生產者和消費者同時對接,阻塞才會解除。
11,可以理解為非緩衝通道是同步傳輸,緩衝通道是非同步傳輸。
12,引發panic的情況:對關閉的通道進行操作;關閉已關閉的通道;
13,元素在通道中傳遞是淺層拷貝。
最好不要從通道的接收方關閉通道,而應從通道的發送方關閉通道
package mainimport "fmt"func main() { chx := make(chan int, 2) // sender go func() { for i := 0; i < 10; i++ { fmt.Printf("Sender: sending element %v...\n", i) chx <- i } fmt.Println("Sender: close the channel...") close(chx) }() // receiver for { elem, ok := <-chx if !ok { fmt.Println("Receiver: closed channel") break } fmt.Printf("Receiver: received an element: %v\n", elem) } fmt.Println("End.")}