为什么所有goroutine都睡着了?

时间:2019-03-05 08:07:52

标签: go concurrency deadlock channel goroutine

以下是代码;

package main

import "fmt"

func main() {
    func1(1)
}

func func1(n int) {
    ch := make(chan int)
    ch <- 1
        for i := range ch {
            fmt.Println(i)
            fmt.Println(<-ch)
        }   
}

当我尝试执行此代码时,它引发以下错误;

fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.func1(0x1, 0x432070)
    /tmp/sandbox451742015/main.go:11 +0x60
main.main()
    /tmp/sandbox451742015/main.go:6 +0x20

1 个答案:

答案 0 :(得分:2)

您的频道是无缓冲的,因此第一次发送将被阻塞,直到有人从该频道接收到。但是之后会从中接收到代码,所以这是一个“立即”死锁。

您可以像ch := make(chan int, 1)一样使它无缓冲,这样发送就不会阻塞,但是您只有一个goroutine,它在一个通道上有一个for range。仅当通道关闭时,此循环才会退出,但您绝不会关闭它。而且您只在其上发送一个值,因此循环被阻塞,等待它可以接收的值或通道关闭。

您需要另一个goroutine在某个时间关闭通道。在循环内部,您无需再次从通道接收信号,循环结构已经做到了。 i将是从通道接收到的值。

有意义的工作示例:

func func1(n int) {
    ch := make(chan int)
    go func() {
        for i := 0; i < 5; i++ {
            ch <- i
        }
        close(ch)
    }()
    for i := range ch {
        fmt.Println(i)
    }
}

这将输出(在Go Playground上尝试):

0
1
2
3
4
相关问题