go - Go 中的无缓冲 channel

标签 go

这是一个关于无缓冲 channel 的简单示例代码:

ch01 := make(chan string)

go func() {
    fmt.Println("We are in the sub goroutine")
    fmt.Println(<-ch01)
}()

fmt.Println("We are in the main goroutine")
ch01 <- "Hello"

我得到的结果:

We are in the main goroutine 
We are in the sub goroutine 
Hello

去 Playground : https://play.golang.org/p/rFWQbwXRzGw

据我了解,发送操作阻塞了主协程,直到子协程在 channel ch01 上执行了接收操作。 .然后程序退出。

像这样在发送操作之后放置子 goroutine 之后:

fmt.Println("We are in the main goroutine")
ch01 <- "Hello"

go func() {
    fmt.Println("We are in the sub goroutine")
    fmt.Println(<-ch01)
}()

发生死锁:

We are in the main goroutine
fatal error: all goroutines are asleep - deadlock!

去 Playground https://play.golang.org/p/DmRUiBG4UmZ

这次发生了什么?这是否意味着在 ch01 <- "Hello" 之后主goroutine立即被阻塞,让sub goroutine没有机会运行?如果是真的,我应该如何理解第一个代码示例的结果?(首先在主协程中,然后在子协程中)。

最佳答案

无缓冲 channel 在发送时阻塞,直到接收方准备好读取。在您的第一个示例中,首先设置了一个阅读器,因此当发送发生时,它可以立即发送。

在你的第二个例子中,发送发生在接收者准备好之前,所以发送阻塞和程序死锁。

您可以通过创建缓冲 channel 来修复第二个示例,但是您有可能永远看不到 goroutine 的输出,因为程序可能会在刷新输出缓冲区之前退出(主 goroutine)。 goroutine 在被调度之前甚至可能不会作为主导出运行。

关于go - Go 中的无缓冲 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49958153/

相关文章:

go - 在Go文本/模板中引用 map 值

go - 将结构内容复制到 Go 中的 uint64

go - 将大型结构的 const 指针传递给函数或 go channel

go - 哪种扫描用于从字符串中读取 float ?

go - 基于接口(interface)抽象实现一个 'Stringer'

go - Go 中的闭包 - 声明将函数作为参数的函数

go - 简单的领导人选举(Stateless leader election)

go - 在类型切换中使用 strconv.FormatFloat() 时遇到问题

struct - Golang 在结构之间切换

go - 如何在 Golang Cloud 函数中重用数据库连接?