使用以下代码可以正常执行
func main() {
count := 10
ch := generate(count)
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
}
func generate(count int) <-chan int {
ch := make(chan int)
go func() {
for i := 0; i < count; i++ {
ch <- i
}
}()
return ch
}
但是换成以下代码,却会提示 fatal error: all goroutines are asleep - deadlock!
func main() {
count := 10
ch := generate(count)
for v := range ch {
fmt.Println(v)
}
}
func generate(count int) <-chan int {
ch := make(chan int)
go func() {
for i := 0; i < count; i++ {
ch <- i
}
}()
return ch
}
想知道使用上述代码时,for-range循环接收造成死锁的原因是什么?这两者的区别是什么?
RangeClause
只有 channel 被关掉才能结束。
是的,close(ch)。关闭之后,这个 channel 无法发送(会 panic),也无法接受(缓存用光后,直接返回 zero value)。
这个估计 go routine 启动之前 ch 就关闭了, range 一个数据都读不到直接退出,main 结束,程序退出。
程序如果没有很快退出,go routine 执行了,向关闭的 ch 写数据会 panic 。
看一眼你的错误:
只有所有的 go routine 全部锁住才会报死锁。但是,你再起一个新的 go routine ,你的发送跟接受的 go routine 都锁住了,但是 main 所在的 go routine 并没有被锁住,所以不会报此错误。