为什么此代码会产生错误?
Why does this code generate an error?
为什么下面的代码会产生错误?
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
一个值被发送到通道,并在下一行被接收。从技术上讲它应该工作。
频道可以缓冲或无缓冲。缓冲通道可以在其“内部”存储多个项目,但是当您向缓冲通道添加内容时,添加项目的 goroutine 只有在另一个 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 可以继续处理。
我现在了解了很多关于频道的知识,现在我可以回答这个问题了。
在第 16 行,当消息 "test" 被主线程(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 的 flow/execution 暂停,直到数据从另一个 goroutine 中的同一通道接收到。
为什么下面的代码会产生错误?
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
一个值被发送到通道,并在下一行被接收。从技术上讲它应该工作。
频道可以缓冲或无缓冲。缓冲通道可以在其“内部”存储多个项目,但是当您向缓冲通道添加内容时,添加项目的 goroutine 只有在另一个 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 可以继续处理。
我现在了解了很多关于频道的知识,现在我可以回答这个问题了。
在第 16 行,当消息 "test" 被主线程(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 的 flow/execution 暂停,直到数据从另一个 goroutine 中的同一通道接收到。