go - 使用缓冲和非缓冲通道遇到麻烦
问题描述
我对 Go 中缓冲通道和无缓冲通道之间的区别有点困惑。例如,下面的代码执行良好:
package main
import "fmt"
func main() {
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
另一方面,当我"ping"
在常规函数中传递消息时,会出现死锁。
package main
import "fmt"
func main() {
messages := make(chan string)
func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
最后,当我使用缓冲通道时,这是固定的,就像这样
package main
import "fmt"
func main() {
messages := make(chan string, 1)
func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
我很困惑为什么第二个案例失败了。Go By Example 说
默认情况下,通道是无缓冲的,这意味着如果有相应的接收 (<- chan) 准备好接收发送的值,它们将只接受发送 (chan <-)。缓冲通道接受有限数量的值,而这些值没有相应的接收器。
msg
在所有三种情况下,水槽不是用于messages
吗?
解决方案
如果未读取无缓冲通道,则它们会阻塞。缓冲通道在达到容量之前不会阻塞。
您的第一个示例实际上启动了一个单独的 go 例程,该例程执行尝试将“ping”写入消息通道的函数。它将阻塞,直到从消息通道读取的语句执行。从消息通道读取的语句能够被命中,因为该函数位于单独的 goroutine 上。
您的第二个示例声明并调用了一个尝试写入消息通道的函数,但该通道永远不会准备好写入,因为您正在同一个主执行线程上执行。从消息通道读取的语句永远不会命中,因为您在写入通道时被阻止。
第三个例子,通道被缓冲并且可以被写入,因为它可以在阻塞之前接受 1 个值。
推荐阅读
- python - 带有动态验证码的 Scrapy
- java - Java - 忽略大小写的映射键查找
- php - 不支持删除到 /oauth/personal-access-tokens/token
- python - 在烧瓶中提交请求时方法不允许错误
- processing.js - 处理获得更高的最大帧速率
- batch-file - 批量双变量?(或绕过它们的方法?)
- scala - SBT 不编译位于自定义测试源文件夹中的测试
- php - 生成随机密码并更新数据库
- javascript - P5.JS - preload() 问题
- windows-store - 代码:0x80073CFB 从 Microsoft Store 下载我自己的应用程序