【发布时间】:2020-07-14 13:18:26
【问题描述】:
这个问题很可能已经被我找不到了,所以我们开始吧:
我有这个 go 函数,它使用 select 语句发送或接收“消息”,无论哪个可用:
func Seek(name string, match chan string) {
select {
case peer := <-match:
fmt.Printf("%s sent a message to %s.\n", peer, name)
case match <- name:
// Wait for someone to receive my message.
我在 4 个不同的 go-routines 上启动这个函数,使用一个无缓冲的通道(使用缓冲区 och 1 会更好,但这只是实验性的):
people := []string{"Anna", "Bob", "Cody", "Dave"}
match := make(chan string)
for _, name := range people {
go Seek(name, match, wg)
现在,我刚刚开始使用 go 并认为由于我们使用的是无缓冲通道,因此“select”的发送和接收语句都应该阻塞(没有人在等待发送消息,所以你可以' t 接收,并且没有人等待接收,因此您无法发送),这意味着函数之间不会进行任何通信,也就是死锁。但是运行代码告诉我们情况并非如此:
API server listening at: 127.0.0.1:48731
Dave sent a message to Cody.
Anna sent a message to Bob.
Process exiting with code: 0
我想问你们这些可爱的人,为什么会这样?编译器是否意识到函数想要在同一个通道中读/写并安排它发生?还是“选择”语句会不断检查是否有任何人可以使用该频道?
对不起,如果这个问题很难回答,我还是个新手,对幕后的事情没有经验:)
【问题讨论】:
-
我猜它开始 goroutines 的引用是你的
main()- 你能展示它的其余部分吗?我猜你的应用会在任何事情发生死锁之前退出。 -
@Adrian 嗨!我不知道发布所有代码的最佳方式,所以我猜this 会这样做(它包含一些我不认为对问题很重要的更改)。问题是我根本不希望程序打印任何东西,我发现程序设法传递任何消息很有趣。
-
一开始我看错了代码,这不是你的
main,而是你的select- 请看我的回答。
标签: go select deadlock channel goroutine