Go學習筆記 通道基本操作

2021-09-01 13:27:03 字數 3636 閱讀 5835

通道(channel)完全可以與 goroutine(也可稱go程)並駕齊驅。

通道型別的值本身是併發安全的,且使用十分方便。

宣告:

1.第乙個引數代表通道的具體型別的型別字面量;

確定通道型別的元素型別;

chan int :元素型別為int的通道型別;

chan string:元素型別為string的通道型別;

2.第二個引數可選,乙個int型別的數值且大於0,表示通道的容量(通道快取元素的個數)

容量=0時:非快取的通道;

容量》0時:緩衝的通道;

非緩衝通道和緩衝通道的資料傳遞方式不同:

3.乙個通道相當於乙個先進先出佇列。

元素值的傳送和接收都要用到 <- 操作符 ,尖括號表示元素值的傳輸方向。

例項:

package main

import "fmt"

func main()

4.對通道的傳送和接收操作都有哪些基本的特性?

(1)對同乙個通道,傳送操作直接是互斥的,接收操作之間也是互斥的;

同一時刻,只能有乙個傳送操作;也只能有乙個接收操作;

即:進佇列時,只能乙個乙個進,出佇列時,只能乙個乙個出。

這裡併發執行指的是:多個**塊分別在不同的gouroutine中,有機會在同一時間執行;

細節:

a.元素從外界進入通道時會被複製,即:進入通道的並不是接收操作符右側的那個值,而是它的副本。

b.元素值從通道進入外界時會被移動。第一步:生成正在通道中的這個元素的副本,並準備給接收方,第二步刪除在通道中的元素值。

(2)傳送操作和接收操作中,對元素值的處理都是不可分割的;

傳送操作要麼還沒複製元素,要麼已複製完畢;(原子操作)

接收操作在準備好元素值的副本後,一定會刪除通道中原值;(原子操作)

(3)傳送操作在完全完成前會被阻塞。接收操作也是如此;

傳送操作 :a.複製元素值   b.放置副本到通道內部

在這兩步完成前,發起傳送操作的那個**會被阻塞;

在通道完成傳送操作後,執行時系統會通知**所在的goroutine ,使它去爭取繼續執行的機會。

接收操作:a.複製通道內的元素; b.放置副本的接收方; c.刪掉原值;

在這三步完成前,發起接收操作的那個**會被阻塞;

在通道完成這些操作後,執行時系統會通知**所在的goroutine,使它去爭取繼續執行的機會。

5.傳送操作和接受操作什麼時候可能被長時間的阻塞?

對於緩衝通道:

如果通道已滿,對於它的所有傳送操作會被阻塞,直到通道中有元素被取走。

此時,通道會優先通知最早等待的goroutine,後者會再次執行傳送操作。

如果通道為空,對於它的接收操作會被阻塞,直到通道中有新的元素值出現。

此時,通道會優先通知最早等待接收的goroutine,並使它再次執行接收操作。

對於非緩衝通道:

無論傳送操作和接收操作,一開始執行就會被阻塞,直到配對的操作也開始執行,才會繼續傳遞。

即:非緩衝通道在用同步的方式傳遞資料。只有收發雙方對接上才傳遞。

資料是直接從傳送方複製給接收方,中間不用緩衝通道做中轉。

相比之下,緩衝通道在用同步方式傳遞資料

大多數情況下,緩衝通道會作為收發雙方的中介軟體。但是,當傳送操作發現通道為空,且正好等待的接收操作時,會直接把元素值複製給接收方。

由於錯誤引發的阻塞:

對於值為nil的通道,不論它的具體型別是什麼,對於它的傳送操作和接收操作都永久處於阻塞狀態。

當只宣告該型別的變數但沒有使用make函式對它進行初始時,該型別變數就是nil。

示例:

package main

func main()

6.傳送操作和接收操作在什麼時候會引發 panic?

(1)對於乙個已經初始化,但未關閉的通道來說,收發操作一定不會引發panic;

但是通道一旦關閉,再對它做傳送操作,就會引發panic。

(2)關閉乙個已經關閉的通道,也會引發painic.

當把接收表示式的結果同時賦給兩個變數時,第二個變數型別一定是bool型別。它的值為false,說明通道已經關閉,並且沒有元素可取了。

(3)如果通道關閉時,還有元素未取出,接收表示式第乙個值,仍是通道中某一元素值,第二個結果值一定是true.

(4) 通過接收表示式的第二個結果值,來判斷通道是否關閉是可能有延時的。關閉通道通常是由傳送方來做。

示例:

package main

import "fmt"

func main()

fmt.println("sender: close the channel...")

close(ch1)

}()// 接收方。

for

fmt.printf("receiver: received an element: %v\n", elem)

}fmt.println("end.")}/*

sender: sending element 0...

sender: sending element 1...

sender: sending element 2...

sender: sending element 3...

receiver: received an element: 0

receiver: received an element: 1

receiver: received an element: 2

receiver: received an element: 3

sender: sending element 4...

sender: sending element 5...

sender: sending element 6...

sender: sending element 7...

receiver: received an element: 4

receiver: received an element: 5

receiver: received an element: 6

receiver: received an element: 7

sender: sending element 8...

sender: sending element 9...

receiver: received an element: 8

receiver: received an element: 9

sender: close the channel...

receiver: closed channel

*/

Go 通道(channel)的基本操作

通道型別是go語言自帶的 唯一乙個可以滿足併發安全性的型別,在宣告並初始化乙個通道時,需要用到內建函式make,傳給make函式的第乙個引數應該代表通道的具體型別的型別字面量。如型別字面量 chan int,其中chan表示通道型別的關鍵字,而int說明了該通道型別的元素型別。在初始化通道時,mak...

go學習筆記01 基本示例

請保持檔案編碼為utf 8 package main 程式入口包必須是main import fmt 匯入使用功能的包,可以在前面使用別命 var a int 定義全域性變數初始為零,型別在後面。未指定情況,標準型別為零,其它為nil var 多賦值方式 a1 int a2 string a3,a4...

Dos基本操作學習筆記

選單,執行,cmd win r shift,右鍵,此處開啟powershell視窗 我的電腦,資料夾路徑前面輸入cmd,回車 以管理員開啟 選單,win系統,命令提示符,管理員身份執行 碟符切換 進入e盤 e 回車 檢視目錄下所有檔案 dir 切換目錄 cd 再從e進入f cd d f 去f中的id...