通達是一個引用,和map類似。map在沒有任何外部引用時,Go語言程序在運行時(runtime)會自動對內存進行垃圾回收(Garbage Collection,GC)。類似的,通道也可以被垃圾回收,但通道也可以被主動關閉。
格式
使用close()來關閉一個通道:
close(ch)
關閉的通道依然可以被訪問,訪問被關閉的通道將會發生一些問題。
給被關閉通道發送數據將會觸發panic
被關閉的通道不會被置爲nil。如果嘗試對已經關閉的通道進行發送,將會觸發宕機;
package main
import "fmt"
func main() {
//創建一個整形的通道
ch := make(chan int)
//關閉通道
close(ch)
//打印通道的指,容量和長度
fmt.Printf("ptr:%p cap:%d Len:%d\n", ch, cap(ch), len(ch))
//給關閉的通道發送數據
ch <- 1
}
代碼運行後觸發宕機
ptr:0xc000016180 cap:0 Len:0
panic: send on closed channel
代碼說明如下:
第 7 行,創建一個整型通道。
第 10 行,關閉通道,注意 ch 不會被 close 設置爲 nil,依然可以被訪問。
第 13 行,打印已經關閉通道的指針、容量和長度。
第 16 行,嘗試給已經關閉的通道發送數據。
提示觸發宕機的原因是給一個已經關閉的通道發送數據。
從已關閉的通道接收數據將不會發送阻塞
從已經關閉的通道數據或者正在接收數據時,將會接收到通道值雷子那個的零值,然後停止阻塞並返回;
操作關閉後的通道:
package main
import "fmt"
func main() {
//創建一個整形的通道
ch := make(chan int, 2)
//給通道放入兩個數據
ch <- 0
ch <- 1
//關閉通道
close(ch)
//遍歷緩衝所有數據,且多個遍歷
for i := 0; i < cap(ch)+1; i++ {
//從通道中讀取數據
v, ok := <-ch
//打印去除數據的狀態
fmt.Println(v, ok)
}
}
代碼運行結果如下:
0 true
1 true
0 false
代碼說明如下:
第 7 行,創建一個能保存兩個元素的帶緩衝的通道,類型爲整型。
第 10 行和第11行,給這個帶緩衝的通道放入兩個數據。這時,通道裝滿了。
第 14 行,關閉通道。此時,帶緩衝通道的數據不會被釋放,通道也沒有消失。
第 17 行,cap() 函數可以獲取一個對象的容量,這裏獲取的是帶緩衝通道的容量,也就是這個通道在 make 時的大小。雖然此時這個通道的元素個數和容量都是相同的,但是 cap 取出的並不是元素個數。這裏多遍歷一個元素,故意造成這個通道的超界訪問。
第 20 行,從已關閉的通道中獲取數據,取出的數據放在 v 變量中,類型爲 int。ok 變量的結果表示數據是否獲取成功。
第 23 行,將 v 和 ok 變量打印出來。
運行結果前兩行正確輸出帶緩衝通道的數據,表明緩衝通道在關閉後依然可以訪問內部的數據。
運行結果第三行的“0 false”表示通道在關閉狀態下取出的值。0 表示這個通道的默認值,false 表示沒有獲取成功,因爲此時通道已經空了。我們發現,在通道關閉後,即便通道沒有數據,在獲取時也不會發生阻塞,但此時取出數據會失敗。