goroutine之间的死锁

goroutine之间的死锁,go,goroutine,Go,Goroutine,我是新来的。当我注释掉第二个goroutine时,出现了一个致命错误。我不明白是什么导致了这个错误的发生。你能给我解释一下吗 package main import ( "fmt" "time" ) func main() { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- i } } () /

我是新来的。当我注释掉第二个goroutine时,出现了一个致命错误。我不明白是什么导致了这个错误的发生。你能给我解释一下吗

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() { 
        for i := 0; i < 10; i++ {
            ch <- i
        }
    } ()
    // go func() { 
        for {
            if num, ok := <-ch; !ok {
                break
            } else {
                fmt.Printf("%d\n", num)
            }
        }
    // } ()
    time.Sleep(2 * time.Second)
    close(ch)
}

从发送goroutine接收所有值后,从ch接收时循环块的接收。运行时检测到程序被卡住和死机

修复方法是在发送所有值后关闭通道:

go func() { 
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
} ()
闭合通道上的接收产生值0,false。接收到的for循环在假值上中断

从程序末尾移除closech


.

从发送goroutine接收所有值后,从ch接收循环块时的接收。运行时检测到程序被卡住和死机

修复方法是在发送所有值后关闭通道:

go func() { 
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
} ()
闭合通道上的接收产生值0,false。接收到的for循环在假值上中断

从程序末尾移除closech


.

因为您没有在第一个goroutine退出之前关闭频道。下面的代码应该可以工作

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() { 
        for i := 0; i < 10; i++ {
            ch <- i
        }
        close(ch)
    } ()
    //go func() { 
        for {
            if num, ok := <-ch; !ok {
                break
            } else {
                fmt.Printf("%d\n", num)
            }
        }
    //} ()
    time.Sleep(2 * time.Second)
}

请在此处尝试:

因为您不会在第一个goroutine退出之前关闭频道。下面的代码应该可以工作

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() { 
        for i := 0; i < 10; i++ {
            ch <- i
        }
        close(ch)
    } ()
    //go func() { 
        for {
            if num, ok := <-ch; !ok {
                break
            } else {
                fmt.Printf("%d\n", num)
            }
        }
    //} ()
    time.Sleep(2 * time.Second)
}

在这里试一试:

谢谢你简洁的解释,Cerise。我不确定我是否完全理解阻塞的概念。这是否意味着接收for循环将永远等待?这是因为下面代码左侧的ok接收到true,但永远不会有另一个num?如果num,ok:=@Pizzas:在您的情况下,num,ok:=@Pizzas在开放频道上接收等待将值发送到该频道。接收循环在接收到来自发送goroutine的所有值后将永远等待。谢谢您的简洁解释,Cerise。我不确定我是否完全理解阻塞的概念。这是否意味着接收for循环将永远等待?这是因为下面代码左侧的ok接收到true,但永远不会有另一个num?如果num,ok:=@Pizzas:在您的情况下,num,ok:=@Pizzas在开放频道上接收等待将值发送到该频道。从发送goroutine接收所有值后,接收循环将永远等待。