为了账号安全,请及时绑定邮箱和手机立即绑定

为什么这段代码会产生错误?

为什么这段代码会产生错误?

Go
慕慕森 2021-11-22 15:07:29
下面的一段代码为什么会产生错误?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一个值被发送到通道,并在下一行被接收。从技术上讲,它应该可以工作。
查看完整描述

2 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

通道可以是有缓冲的无缓冲的。一个缓冲通道可以在它的“内部”存储许多项目,但是当你向缓冲通道添加一些东西时,添加项目的 goroutine 只能在另一个 goroutine 删除项目时继续。没有地方可以“离开”这个项目,它必须直接传递给另一个 goroutine,第一个 goroutine 会等到另一个 goroutine 从它那里拿走这个项目。

这就是您的代码中发生的事情。当您使用 来创建频道时make,如果您没有将容量指定为第二个参数,您将获得一个无缓冲频道。要创建缓冲通道,请将第二个参数传递给make例如

messages := make(chan string, 1) // could be larger than 1 if you want

这允许 goroutine 将项目(string在本例中为a )添加到通道中,当另一个 goroutine 将来尝试从通道中获取项目时,该项目将可用,然后原始 goroutine 可以继续处理。


查看完整回答
反对 回复 2021-11-22
?
慕侠2389804

TA贡献1719条经验 获得超6个赞

我现在已经了解了很多关于频道的知识,现在我可以回答这个问题了。


在第 16 行,当主线程(goroutine)将消息“test”发送到通道时,执行会暂停,运行时会寻找其他准备好从通道消息接收值的 goroutine。由于没有其他通道,运行时会引发带有死锁消息的恐慌。这是死锁的典型例子。


要解决这个问题,可以做两件事。


1)按照马特的建议使用缓冲通道(答案之一)。


2) 否则在 goroutine 中有发送到 channel 或从 channel 接收的语句。


func main() {


    messages := make(chan string)


    go func() {

        messages <- "test" //line 16

    }()

    fmt.Println(<-messages)


}

所以最重要的一点是,


1) 通道只能用于 goroutines 之间的通信,即当你发送到一个 goroutine 中的通道时,你只能在另一个不同的 goroutine 中接收它。


2) 当数据发送到 goroutine 中的通道时,该 goroutine 的流程/执行将暂停,直到从另一个 goroutine 中的同一通道接收到数据。


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 158 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信