Goroutine中不包含关键字“ go”的比较

Vog*_*guo -2 channel go goroutine

以下代码记录了一个错误:

致命错误:所有goroutine都在睡着-死锁!

package main

import "fmt"

func main() {
    ch := make(chan int)
    ch <- 1
    fmt.Println(<-ch)
}
Run Code Online (Sandbox Code Playgroud)

但是,当我将代码更改为:

package main

import "fmt"

func assign (ch chan int) {
    ch <- 1
}

func main() {
    ch := make(chan int)
    go assign (ch)

    fmt.Println(<-ch)
}
Run Code Online (Sandbox Code Playgroud)

打印出“ 1”。

然后我使用了缓冲通道:

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}
Run Code Online (Sandbox Code Playgroud)

也可以打印“ 1”和“ 2”。

我对此情况有些困惑。提前致谢!

Nik*_*Nik 5

僵局发生的原因:

在第一个代码段中,您只有一个主要的goroutine,当您尝试在此处写入通道时,它会被阻塞:

ch <- 1
Run Code Online (Sandbox Code Playgroud)

因为没有人从通道读取数据,所以主goroutine正在等待继续进行。

参见有效转到->渠道

如果通道未缓冲,则发送方将阻塞,直到接收方收到该值为止。

发送者是main功能,接收者也是main功能。

如何避免僵局:

为了解决这个问题,您有两种选择:

选项1:按以下方式ch缓冲通道:

ch := make(chan int, 1) // buffer length is set to 1
Run Code Online (Sandbox Code Playgroud)

巡回演出

仅在缓冲区已满时发送到缓冲的通道块。

因此,您可以写入通道,直到缓冲区已满。然后,必须有人从该频道开始阅读。

选项2:像在第二个代码段中一样,从goroutine写入通道:

func assign(ch chan int) {
    ch <- 1
}

func main() {
    ch := make(chan int)
    go assign(ch) // does not block the main goroutine
    fmt.Println(<-ch) // waiting to read from the channel
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,main功能将一直执行到fmt.Println(<-ch)从通道读取后立即继续。