go channel 这段代码为什么报错

2023-08-03 18:14:05 +08:00
 tqz

这段代码为什么报错

func main() {
	ch := make(chan int)
	<-ch
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()

我刚开始学习 go ,按照网上的教程说读取无缓冲通道时,如果没有数据写入就会一直阻塞,但实际上却报错了,难道是因为在 main 里面的缘故?或者是根本没有发送者的缘故?

各位大佬们,请问学习 channel 有什么让人醍醐灌顶的提醒吗?感谢您的指点!

补充:有无缓冲都报错


func main() {
	ch := make(chan int, 1)
	//go func() {
	//	time.Sleep(time.Second * 3)
	//	ch <- 1
	//}()
	<-ch
}
1473 次点击
所在节点    程序员
12 条回复
tyrantZhao
2023-08-03 18:21:08 +08:00
main 也是个 channel ,so 瞅瞅是不是就死锁了?
mcfog
2023-08-03 18:23:43 +08:00
因为阻塞了,所以 all goroutines are asleep 。因为 all goroutines are asleep ,所以 deadlock 。因为 deadlock ,所以报错了
weirdo
2023-08-03 18:25:51 +08:00
all goroutines are asleep - deadlock!

写的很清楚了,main 里面阻塞了,就相当于这个程序执行开出来的所有 goroutines 都 sleep 了,死锁了。
ScepterZ
2023-08-03 18:27:28 +08:00
相当于 go 有一点主动识别死锁的功能,他检查到程序已经不可能运行下去了,所以给你报错了,而不是真的卡主
clikes
2023-08-03 19:31:32 +08:00
这里确实是阻塞了,但是这里报错是因为所有的 goroutine 都阻塞了,如果你想看这个现象的话 可以创建两个 goroutine ,然后阻塞其中一个。
jinsp
2023-08-03 19:49:35 +08:00
jinsp
2023-08-03 19:50:53 +08:00
可以直接跟 GPT 学习
alsas
2023-08-03 20:06:35 +08:00
main 函数启动也是一个 goroutine 死锁了
lasuar
2023-08-03 20:08:37 +08:00
KaynW
2023-08-03 20:12:21 +08:00
golang 的检测机制, 当运行的 M 为 0 时就会这样, golang 认为出现了 deadlock
sirz
2023-08-03 20:17:02 +08:00
### GPT3.5 回复:

这段代码报错的原因是因为您在 main 函数中创建了一个整型类型的通道 ch ,然后立即尝试从该通道接收数据。但是在没有其他协程往该通道发送数据的情况下,该操作会导致程序阻塞,因此编译器会报错。

要解决这个问题,您可以通过以下方式之一:

1. 在<-ch 操作之前,在另外一个协程中使用 go 关键字发送数据到通道,例如:go func() { ch <- 1 }()
2. 使用 channel 的缓冲区,例如:ch := make(chan int, 1),这样就可以先往通道中写入一个数据,然后再进行接收操作。
3. 删除<-ch 操作,这样代码将不再尝试从通道接收数据,不会引发阻塞。

请根据您的需求选择适合的方法来修改代码。如果还有其他问题,请随时提问。


### GPT4 回复:

这段代码中的错误源于它试图从一个没有接收任何值的通道中读取数据。在 Go 语言中,尝试从空的通道读取数据会导致程序阻塞。

以下是你的代码:

func main() {
ch := make(chan int)
<-ch // 这里尝试从空的通道读取数据,导致程序阻塞
}
要想解决该问题,你需要确保在尝试从通道 ch 读取数据之前,该通道已经接收到了某个值。以下是一种可能的解决方案:

go
func main() {
ch := make(chan int)

go func() { // 创建一个新的 goroutine 来向通道发送数据
ch <- 1
}()

fmt.Println(<-ch) // 现在可以从通道中安全地读取数据
}
在这个修改后的版本中,我们创建了一个新的 goroutine 来向通道 ch 发送一个整数值,这样主函数就可以从 ch 中读取数据而不会被阻塞。
zhangkunkyle
2023-08-04 10:39:25 +08:00
未初始化的 channel
1.读、写会死锁,关闭会 panic

已初始化的无缓冲 channel
1. 只写、只读会死锁
2. 一个协程内顺序先读后写、先写后读会死锁
3. 主协程先写,然后新开协程读会死锁(新开协程先读、然后主协程写就不会死锁了)
4. 新开协程写,主协程读,如果写完不 close ,读的时候也会死锁

已初始化的有缓冲 channel
1. 只读会死锁,只写超过缓冲数会死锁
2. 读写都有的情况下,写满了还写,读空了还读,会死锁
3. 一个协程里写一定要在读之前,读空的会死锁

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/962174

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX