为了账号安全,请及时绑定邮箱和手机立即绑定

为什么延迟函数不执行?

为什么延迟函数不执行?

Go
杨魅力 2023-08-21 14:41:04
我正在努力理解 Go 中的并发性。package mainimport "fmt"func sendValues(myIntChannel chan int) {    for i := 0; i < 5; i++ {        myIntChannel <- i //sending value    }}func main() {    myIntChannel := make(chan int)    defer close(myIntChannel)    go sendValues(myIntChannel)    for value := range myIntChannel {        fmt.Println(value) //receiving value    }}上面的代码给出以下输出:01234fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:main.main()    /Users/spikki/Desktop/GoLearning/go_channel.go:51 +0x10b根据我的理解,延迟函数将在其周围函数完成后执行。我无法解释它。如果我使用 for 循环从通道接收值,其工作原理如下。for i := 0; i < 5; i++ {    fmt.Println(<-myIntChannel) //receiving value}谁能帮助我理解这个概念?
查看完整描述

2 回答

?
BIG阳

TA贡献1859条经验 获得超6个赞

for ... range仅当从通道接收到所有值并且通道已关闭时,通道上的操作才会终止。


在您的示例中,您希望在延迟函数中关闭通道,但这只会在main()返回时运行。但main()只有在循环结束时才会返回。这就是死锁的原因。循环for等待通道关闭,关闭通道等待for循环结束。


当您使用循环从通道接收恰好 5 个值时,它会起作用,因为启动的 Goroutine 会在其上发送 5 个值。该循环不会等待通道关闭,因此循环可以结束,函数也可以结束main()。


这就是为什么发送者应该关闭通道(而不是接收者),问题就立即解决:


func sendValues(myIntChannel chan int) {

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

        myIntChannel <- i //sending value

    }

    close(myIntChannel)

}


func main() {

    myIntChannel := make(chan int)

    go sendValues(myIntChannel)


    for value := range myIntChannel {

        fmt.Println(value) //receiving value

    }

}

输出(在Go Playground上尝试):


0

1

2

3

4


查看完整回答
反对 回复 2023-08-21
?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

用稍微不同的术语来解释它,您的代码的作用是:


func main() {

    ...

    while myIntChannel is not closed {

        ...

    }

    close myIntChannel 

}

现在您可以看到僵局从何而来。


虽然上面的答案是有效的,但如果您更喜欢使用,您也可以尝试这个defer:


func sendValues(myIntChannel chan int) {

    defer close(myIntChannel)

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

        myIntChannel <- i //sending value

    }

}


func main() {

    myIntChannel := make(chan int)


    go sendValues(myIntChannel)


    for value := range myIntChannel {

        fmt.Println(value) //receiving value

    }

}


查看完整回答
反对 回复 2023-08-21
  • 2 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信