go - Goroutine 中关于关键字 "go"和没有关键字的比较

标签 go channel goroutine

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

fatal error: all goroutines are asleep - deadlock!

package main

import "fmt"

func main() {
    ch := make(chan int)
    ch <- 1
    fmt.Println(<-ch)
}

但是当我把代码改成这样的时候:

package main

import "fmt"

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

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

    fmt.Println(<-ch)
}

打印出“1”。

然后我使用缓冲 channel :

package main

import "fmt"

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

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

我对这种情况有点困惑。提前致谢!

最佳答案

为什么会发生死锁:

在第一个代码片段中,您只有一个主 goroutine,当您尝试写入此处的 channel 时它被阻止了:

ch <- 1

因为没有人从 channel 中读取并且主 goroutine 正在等待它继续。

参见 Effective Go -> Channels

If the channel is unbuffered, the sender blocks until the receiver has received the value.

发件人是main功能,接收者也是main功能。

如何避免死锁:

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

选项 1:制作 ch像这样缓冲的 channel :

ch := make(chan int, 1) // buffer length is set to 1

来自 A Tour of Go

Sends to a buffered channel block only when the buffer is full.

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

选项 2: 从 goroutine 写入 channel ,就像您在第二个代码片段中所做的那样:

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
}

在这种情况下 main函数将执行到 fmt.Println(<-ch)并在可以从 channel 读取后立即继续。

关于go - Goroutine 中关于关键字 "go"和没有关键字的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55297458/

相关文章:

go - defer 会一直等到子程序执行完吗?

function - Go语言中如何调用另一个函数内的函数?

for-loop - 遍历 channel 时出现错误 "too many variables in range"

channel - 检查nextflow channel 是否为空

go - 带有sync.waitGroup的Goroutine每次输出不同的值

go - 试图避免 goroutine 泄漏时出现 panic

windows - 在终端的 Windows 中优雅地退出 golang

go - 多个串行请求导致缓冲区为空

Golang 生产者 channel 作为参数或作为返回值

go - 如何从 goroutine 结束一个 go 程序