1. 程式人生 > >go語言學習-chan使用過程關於close()

go語言學習-chan使用過程關於close()

chan在go語言中相當於一個檔案操作符,使用完成之後需要使用Close()函式關閉。

下面這段程式碼有兩個chan,ch1是一個chan int型別,ch2是一個chan bool型別,ch1被write()函式寫入10個數,被read()函式讀取,ch2其實是為了防止main所在的goroutine提前退出用的。

我們分別在寫完之後Close()和不Close()看看有什麼不同。

package main

import "fmt"

func read(ch1 chan int,ch2 chan bool){
    for{
        fmt.Printf("read a int is %d\n"
,<-ch1) } ch2 <- true } func write(ch chan int){ for i:=0;i<10;i++{ ch <- i } //close(ch) } func main() { ch1 := make(chan int) ch2 := make(chan bool) go write(ch1) go read(ch1,ch2) <-ch2 }

下面是不close()的執行結果:
這裡寫圖片描述
從執行結果可以看到,當我們將10個數寫完之後,如果不close()ch1,read就會阻塞,程式中所有的協程都被阻塞,ch2無法寫入,也無法讀取,系統這時候檢測到這種錯誤就會報錯。


當我們把close()開啟之後,再執行一遍,看看執行的結果:
這裡寫圖片描述
我們這次可以看到close之後,read函式在讀完10個數字之後,也不會阻塞會一直讀取到0,ch2也不會因為沒有寫入和讀取導致整個程式報錯。所以我們每次在使用chan完成之後一定要記得關閉,這樣即使我們讀端沒有做讀完處理,程式也不會出錯。
下面是這個例子的正確寫法,我們在讀取chan時可以根據,第二個返回值,判斷寫端是否關閉,如果寫端關閉,則會讀取到false,通過close()和讀取端根據讀chan第二個返回值可以確保管道在讀寫兩端能夠做到寫多少讀多少,程式也能很友好的退出。

package main

import "fmt"
func read(ch1 chan int,ch2 chan bool){ for{ v ,ok:= <- ch1 if ok{ fmt.Printf("read a int is %d\n",v) }else{ ch2 <- true } } } func write(ch chan int){ for i:=0;i<10;i++{ ch <- i } close(ch) } func main() { ch1 := make(chan int) ch2 := make(chan bool) go write(ch1) go read(ch1,ch2) <-ch2 }

下面是執行結果:
這裡寫圖片描述