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)