猿问

为什么我的代码在没有关闭通道的情况下陷入僵局?

我正在尝试编写一个程序:


package main


import (

    "fmt"

    "sync"

)


func main() {

    n := 4

    resChan := make(chan []int, n)

    res := []int{}

    var wg sync.WaitGroup

    for i := 0; i < n; i++ {

        wg.Add(1)

        go func(i int) {

            defer wg.Done()

            resChan <- append(res, i)

        }(i)

    }

    wg.Wait()


    close(resChan) // code will deadlock without this

    for subRes := range resChan {

        res = append(res, subRes...)

    }

    fmt.Printf("%v", res)

}

我认为我有一个缓冲通道,因此对通道的写入不会阻塞。但是,我得到了:


fatal error: all goroutines are asleep - deadlock!


goroutine 1 [chan receive]:

main.main()

    /tmp/sandbox562058728/prog.go:23 +0x14c

有人可以解释为什么代码会这样吗?


aluckdog
浏览 84回答 2
2回答

慕桂英546537

在通道关闭之前,测距通道不会退出 for 循环。

牛魔王的故事

如果通道没有关闭,循环将永远不知道何时停止迭代过程。range-loop 无法从通道中读取,因为它在写入过程中被锁定。另一方面,没有更多数据要通过通道发送。因此,通道在写入过程中被锁定,并且永远不会被解锁。然后它会导致死锁。Golang Tour页面上有写的注释说:注意:只有发送方应该关闭通道,接收方不能。在关闭的通道上发送会引起恐慌。另一个注意事项:频道不像文件;您通常不需要关闭它们。仅当必须告诉接收器没有更多值到来时才需要关闭,例如终止范围循环。
随时随地看视频慕课网APP

相关分类

Go
我要回答