Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 为什么接收器被阻塞没有错误?_Go_Channel_Goroutine - Fatal编程技术网

Go 为什么接收器被阻塞没有错误?

Go 为什么接收器被阻塞没有错误?,go,channel,goroutine,Go,Channel,Goroutine,根据: 接收器总是阻塞,直到有数据要接收 此测试应失败,因为对于来自通道的最后一次接收操作,没有相应的写入: package main import "fmt" func main() { c := make(chan int) for i := 0; i < 4; i++ { // 4 async reads go func() { fmt.Println("received:", <-c) }()

根据:

接收器总是阻塞,直到有数据要接收


此测试应失败,因为对于来自通道的最后一次接收操作,没有相应的写入:

package main

import "fmt"

func main() {
    c := make(chan int)    
    for i := 0; i < 4; i++ { // 4 async reads
      go func() {
            fmt.Println("received:", <-c)
         }()

    }    
    // just 3 writes, 1 write is missing
    c <- 1   
    c <- 2 
    c <- 3   
}
主程序包
输入“fmt”
func main(){
c:=制造(成交量)
对于i:=0;i<4;i++{//4异步读取
go func(){

fmt.Println(“received:”,这里没有死锁,因为
main
goroutine没有被阻止。它在
c
上发送3个值,成功是因为有4个启动的goroutine从它那里接收,然后它结束。随着它结束你的应用程序,它不会等待其他非
main
goroutine结束。请参阅

死锁意味着所有goroutine都被阻塞。这里不是这样

尝试从没有人(当前或曾经)准备好发送的通道接收不是错误。如果事实如此,这是完全正常的。这是通道的一个用例:它充当同步工具,您可以发送/接收,操作将阻塞,直到另一端也准备好

在某些情况下,即使是在整个应用生命周期内被阻止的goroutine也是正常的,例如,goroutine可能会等待用户输入,例如CTRL+BREAK,用户可能永远不会按下,应用可能会正常结束

因此,这并不被视为错误,也不会为此打印错误或警告消息。但如果您感到好奇,很容易实现它。只需在您的
main()
中添加一个延迟函数,它将被称为
main()
函数之前的最后一个函数(以及您的应用程序)结束。打印正在运行的goroutine的数量:

func main() {
    defer func() {
        fmt.Println("Remaining goroutines:", runtime.NumGoroutine()-1) //-1 for main
    }()

    // your code
}
通过此添加,输出将为:

received: 1
received: 2
received: 3
Remaining goroutines: 1
如果将循环更改为启动14个goroutine而不是1个,则输出将显示还有11个goroutine


最后一点注意:因为在你的应用程序中,
main()
函数不会等待其他goroutine结束,它们在调用延迟函数时可能仍然处于活动状态,因此它们可能会也可能不会包含在剩余goroutine计数中。如果您使用例如
sync.WaitGroup
来等待它们结束,那么它们肯定不会被包含。请参阅示例。

但READ goroutine必须被阻止,因为缺少1次写入。但仍然没有任何错误指示被阻止的读取routine@AgniusVasiliauskas是的,goroutine在应用程序结束前会被阻止,那又怎样?这不是错误,也不是死锁。我将死锁改为“错误”。这不是重点。重点是为什么没有错误/信息消息表明某些goroutine被阻止。在我看来,这个程序是无效的,至少必须生成一些关于被阻止例程的消息。为什么不是这样?被阻止的多个goroutine中只有一个是正常的。Go并不试图预测未来:goroutine可能会在一小时、一天或一年内被解锁。此外,在这一点上
main()
退出,因此
fmt.Println(3)
也不保证执行死锁检测器。@AgniusVasiliauskas不,它不执行。它只是表明它等待的条件在程序的生命周期中从未发生过。goroutine可能正在等待用户的事件(例如,
ctrl+break
键),但用户可能永远不会按这些键,应用程序可能会正常结束。“此测试应该失败,因为对于来自通道的最后一次接收操作,没有相应的写入”,为什么测试会失败?确实“没有相应的写入”但是测试实际上没有检查通道上的任何尝试接收是否完成。在我看来,至少运行时可以通知用户退出程序后有多少goroutines在没有收到数据的情况下被终止。也就是说,我希望收到信息性消息。我想这会增加价值。您的意见与工作方式不符很不幸。
received: 1
received: 2
received: 3
Remaining goroutines: 1