以下代码会产生错误原因?
func main() {
messages := make(chan string)
messages <- "test" //line 16
fmt.Println(<-messages)
}
生成以下错误。
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/tmp/sandbox994400718/main.go:16 +0x80
一个值被发送到该频道,并在下一行中被接收。从技术上讲它应该有用。
答案 0 :(得分:4)
频道可以缓冲或无缓冲。缓冲通道可以在其内部存储多个项目,但是当您向缓冲通道添加内容时,添加该项目的goroutine只能在另一个goroutine移除该项目时继续。没有地方“离开”该项目,它必须直接传递到另一个goroutine,并且第一个goroutine将等到另一个从该项目中取出该项目。
这是您的代码中发生的事情。使用make
创建频道时,如果未指定容量作为第二个参数,则会获得无缓冲的频道。要创建缓冲通道,请将第二个参数传递给make
,e.g。
messages := make(chan string, 1) // could be larger than 1 if you want
这允许goroutine将项目(在这种情况下为string
)添加到频道,当另一个goroutine将来尝试从频道获取项目时,它将可用,并且原始goroutine然后可以继续处理。
答案 1 :(得分:0)
我现在已经学到了很多关于频道的知识,现在我能够回答这个问题了。
在第16行,当消息&#34; test&#34;由主线程(goroutine)发送到通道 执行暂停 ,运行时查找准备从通道消息接收值的其他goroutine。由于没有其他通道,运行时会引发死锁消息的恐慌。这是死锁的典型例子。
要解决这个问题,可以做两件事。
1)使用Matt建议的缓冲通道(其中一个答案)。
2)否则在go例程中有发送到频道或从频道接收的声明。
func main() {
messages := make(chan string)
go func() {
messages <- "test" //line 16
}()
fmt.Println(<-messages)
}
因此,基本的消除是,
1)频道只能用于在goroutine之间进行通信,即当您在一个goroutine中发送到频道时,您只能在另一个不同的goroutine中接收它。
2)当数据被发送到goroutine中的通道时,该goroutine的流/执行暂停,直到从另一个goroutine中的同一通道接收数据。