Channel:
一、channel簡介
channel即通道,是goroutine之間溝通的橋樑,大都是阻塞同步的,是引用類型。
1、定義和創建channel;
channel的類型:chan + 數據類型,如:chan bool
創建channel:可以通過make函數來創建channel,第一個參數是channel的類型(如:chan bool),第二個參數是channel的緩存大小(可不填,不填則表示設置緩存爲0)。
示例如下:
var _channel chan bool //聲明channel
_channel := make(chan bool, 100) //創建channel
2、通過close關閉;
close(_channel)
3、可以通過for range來迭代操作;
for v := range _channel {
fmt.Println(v)
}
對線channel進行迭代操作時,必須在迭代的過程中明確關閉這個channel,並且保證channel被關閉成功!【調用close(_channel)】,否則會發生死鎖,導致程序崩潰退出!
報錯提示:fatal error: all goroutines are asleep - deadlock!
4、可以設置單向或雙向通道;
雙向通道:make創建的channel是雙向通道,即channel值既可以存也可以取。
單向通道:分爲兩種:1、channel值只能存;2、channel值只能取。
5、可以設置緩存大小,在未被填滿前不會發生阻塞;
無緩存是同步阻塞的,有緩存是異步的,這一點詳細解釋請看下一章【golang--channel緩存大小與線程阻塞的關係】
二、channel的具體操作實例:
1、通過channel來實現線程之間的通信;
完整代碼如下:
package main
import (
"fmt"
"time"
)
func main() {
_channel := make(chan bool)
go func() {
fmt.Println("新線程運行開始...")
//讓線程等待2秒
time.Sleep(2 * time.Second)
fmt.Println("新線程運行結束...")
_channel <- true
}()
//main函數運行到這裏,會發生阻塞,直到channel獲得期待的值,纔會繼續往下運行.
<-_channel
//由於main函數執行完畢後,函數裏的局部變量都會被釋放,所以我們可以不對channel進行close操作.
fmt.Println("main函數運行結束...")
}
本例藉助channel實現了main線程與創建的goroutine之間的通信,運行結果如下:
新線程運行開始...
新線程運行結束...
main函數運行結束...
2、對channel進行迭代操作:
package main
import (
"fmt"
"time"
)
func main() {
_channel := make(chan bool)
go func() {
fmt.Println("新線程運行開始...")
//讓線程等待2秒
time.Sleep(2 * time.Second)
fmt.Println("新線程運行結束...")
_channel <- true
//需要對channel執行關閉操作,否則在main函數中channel會一直進行迭代操作,永遠處於阻塞狀態,進而導致程序崩潰
close(_channel)
}()
//main函數運行到這裏時,會發生阻塞,等待channel獲得期望的值
for v := range _channel {
//當channel獲得期望的值時纔會執行到這裏
fmt.Println("channel的值爲:", v)
}
fmt.Println("main函數運行結束...")
}
運行結果如下:
新線程運行開始...
新線程運行結束...
channel的值爲: true
main函數運行結束...