fatal error: all goroutines are asleep - deadlock!
这个错误的原因是:
在main goroutine线,期望从管道中获得一个数据,而这个数据必须是其他goroutine线放入管道的
但是其他goroutine线都已经执行完了(all goroutines are asleep),那么就永远不会有数据放入管道。
所以,main goroutine线在等一个永远不会来的数据,那整个程序就永远等下去了。
这显然是没有结果的,所以这个程序就说“算了吧,不坚持了,我自己自杀掉,报一个错给代码作者,我被deadlock了”
证明如下:
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go func() {
for i := 0; i < 10; i++ {
c <- i
}
}()
hold(c)
}
func hold(c <-chan int) {
for {
time.Sleep(1 * time.Second)
fmt.Println(<-c)
}
fmt.Println("hold on ...")
}
hold方法中无线循环获取数据,显然循环10次,就没有数据可以取了,于是抛出fatal error
再看一段测试代码
package main
import (
"fmt"
)
func afuntion(ch chan int) {
fmt.Println("finish")
<-ch
}
func main() {
ch := make(chan int)
ch <- 1
go afuntion(ch)
}
这段代码同样会造成死锁,原因是 channel没有缓冲,相当于channel一直都是满的,所以这里会发生阻塞。下面的goroutine还为创建,所以程序会在此一直阻塞,然后。。。就挂掉了。。。
上面代码稍微修改下,就可以正常运行,如下
package main
import (
"fmt"
)
func afuntion(ch chan int) {
fmt.Println("finish")
<-ch
}
func main() {
ch := make(chan int)
go afuntion(ch)
ch <- 1
}
解释:
1. 创建了一个无缓冲channel
2. 启动了一个goroutine,这个routine中对channel执行取出操作,但是因为这时候channel为空,所以这个取出操作发生阻塞,但是主routine可没有发生阻塞,程序继续运行
3. 往channel中放入了一个数据
4. 这时阻塞的那个routine检测到了channel中存在数据了,所以接触阻塞,从channel中取出数据,程序就此完毕