由于以下代码中的某种原因,我收到“致命错误:所有goroutine都在睡眠-死锁!”。我正在使用应该不阻塞的缓冲通道。不知道我在做什么错
package main
import (
"fmt"
"sync"
)
func main() {
c := make(chan int, 2)
var wg sync.WaitGroup
wg.Add(2)
go doSomething(c, wg)
go doSomething(c, wg)
go doSomething(c, wg)
wg.Wait()
close(c)
for v := range c {
fmt.Print(v)
}
}
func doSomething(c chan<- int, wg sync.WaitGroup) {
defer wg.Done()
c <- 1
}
游乐场链接https://play.golang.org/p/J9meD5aKna
虽然您的解决方案可能会起作用,但我对此并不满意。
首先,您需要更改通道大小以使其起作用这一事实表明存在潜在的问题/错误。现在,每次您要启动另一个时doSomething
,都必须记住要更改通道的长度。
其次,您要等到所有goroutine完成后才能从通道读取。这是一种“浪费”,因为通道范围循环的要点之一是您不必等到所有项目生成(写入通道)后,就可以立即处理这些项目。他们已经准备好了。
所以我会像这样写你的代码
func main() {
c := make(chan int)
var wg sync.WaitGroup
wg.Add(3)
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
wg.Wait()
defer close(c)
}()
for v := range c {
fmt.Print(v)
}
}
func doSomething(c chan<- int) {
c <- 1
}
https://play.golang.org/p/T3dfiztKot
请注意,等待和关闭通道现在是如何在其自己的goroutine中进行的-这允许立即开始在通道上进行迭代(该通道现在没有缓冲!)。
我还更改了代码,以WaitGroup
使它永远不会离开声明它的范围(即,它不用作参数),这是我个人的喜好。我相信它使代码更易于遵循和理解。
问题内容: 这仅适用于至少两个发送到通道的设备。在deviceChan中只有一台设备时,该功能不会接收任何东西。通道在WriteDeviceToFile到达之前消失了吗? 问题答案: 返回时程序退出。写入文件之前没有任何阻止
问题内容: 输出: 问题答案: 之所以陷入僵局,是因为结构是通过值而不是通过引用传递的。 将WaitGroup传递给函数时,需要传递 指针 而不是值。否则,将使用WaitGroup的副本。 这是您的工作示例:
问题内容: 我有三个并发的go例程,如下所示, 该逻辑代码每次都会出现死锁情况。实际上,当它运行时,只需多次执行例程1的打印语句(*标记之间的语句)(尽管我的打印语句只有一个)并给出死锁错误。有人可以告诉我代码逻辑有什么问题吗?谢谢。 注意 有关更多信息,请参见http://play.golang.org/p/pW6aXryUaK,此处仅执行行号290。包含错误的原始代码可以在play.golan
我使用deadLetterChannel来处理异常,并将它们发送到错误队列。 是否可以使用其他邮件标头来丰富邮件?还是我必须为此使用 onException?
问题内容: 当我执行一些go实践代码时,遇到一个问题,通道可以关闭两次,如下所示: 输出: 但是,当我手动关闭通道两次时,我得到了。 为什么上面的代码可以两次关闭? 问题答案: 一个通道只能关闭一次,尝试关闭一个已关闭的通道紧急情况。 但接收从封闭通道没有限制,从关闭信道接收: 封闭通道上的接收操作始终可以立即进行,在接收到任何先前发送的值之后,得出元素类型的零值。 Go应用程序运行直到其主要go
问题内容: 在Gorilla websocket的示例目录中,有一个名为hub.go的文件。 https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go 在这里,您可以在类型中心上找到执行此操作的方法。 为什么在这样的最后一种情况下,它不仅仅直接发送到c.send通道? 问题答案: 保证无阻塞发送到通道的方法。如果c.