Go語言關閉通道後繼續使用通道

通達是一個引用,和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 表示沒有獲取成功,因爲此時通道已經空了。我們發現,在通道關閉後,即便通道沒有數據,在獲取時也不會發生阻塞,但此時取出數據會失敗。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章