channel默認上是阻塞的,也就是說,若是Channel滿了,就阻塞寫,若是Channel空了,就阻塞讀。阻塞的含義就是一直等到輪到它爲止。單有時候咱們會收到 fatal error: all goroutines are asleep - deadlock! 異常,這是如何呢? 協程
代碼例子:blog
package main get
import "fmt" string
func main() {
channel := make(chan string, 2) it
fmt.Println("1")
channel <- "h1"
fmt.Println("2")
channel <- "w2"
fmt.Println("3")
channel <- "c3" // 執行到這一步,直接報 error
fmt.Println("...")
msg1 := <-channel
fmt.Println(msg1)
}io
執行效果:import
參考:select
fatal error: all goroutines are asleep - deadlock! 程序
出錯信息的意思是:
在main goroutine線,指望從管道中得到一個數據,而這個數據必須是其餘goroutine線放入管道的
可是其餘goroutine線都已經執行完了(all goroutines are asleep),那麼就永遠不會有數據放入管道。
因此,main goroutine線在等一個永遠不會來的數據,那整個程序就永遠等下去了。
這顯然是沒有結果的,因此這個程序就說「算了吧,不堅持了,我本身自殺掉,報一個錯給代碼做者,我被deadlock了」
這裏是系統自動在除了主協程以外的協程都關閉後,作的檢查,繼而報出的錯誤, 證實思路以下, 在100秒內, 咱們看不到異常, 100秒後,系統報錯。
package main
import (
"fmt"
"time"
)
func main() {
channel := make(chan string, 2)
go func() {
fmt.Println("sleep 1")
time.Sleep(100 * time.Second)
fmt.Println("sleep 2")
}()
fmt.Println("1")
channel <- "h1"
fmt.Println("2")
channel <- "w2"
fmt.Println("3")
channel <- "c3"
fmt.Println("...")
msg1 := <-channel
fmt.Println(msg1)
}
100秒內執行效果截圖:
100秒後執行效果截圖:
若是避免上面異常拋出呢?這時候咱們能夠用 select來幫咱們處理。
package main
import "fmt"
func main() {
channel := make(chan string, 2)
fmt.Println("1")
channel <- "h1"
fmt.Println("2")
channel <- "w2"
fmt.Println("3")
select {
case channel <- "c3":
fmt.Println("ok")
default:
fmt.Println("channel is full !")
}
fmt.Println("...")
msg1 := <-channel
fmt.Println(msg1)
}
執行效果:
這時候,咱們把第三個要寫入的 chan 拋棄了。
上面的例子中是寫的例子, 讀的例子也同樣,下面的異常是 ws := <-channel 這一行拋出的。
channel := make(chan string, 2)
fmt.Println("begin")
ws := <-channel
fmt.Println(ws)