当我执行一些go实践代码时,遇到一个问题,通道可以关闭两次,如下所示:
// jobs.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
jobs := make(chan int, 5)
done := make(chan bool)
go func() {
for {
j,more := <-jobs
fmt.Println("receive close: ", j, more)
done <- true
}
}()
close(jobs)
<- done
}
输出:
~ go run jobs.go
Hello, playground
receive close: 0 false
receive close: 0 false
但是,当我手动关闭通道两次时,我得到了panic: close of closed channel
。
为什么上面的代码可以两次关闭?
一个通道只能关闭一次,尝试关闭一个已关闭的通道紧急情况。
但接收从封闭通道没有限制,从关闭信道接收:
封闭通道上的接收操作始终可以立即进行,在接收到任何先前发送的值之后,得出元素类型的零值。
Go应用程序运行直到其主要goroutine运行(在“正常”情况下)为止,或者从另一个角度来看:Go应用程序在其主要goroutine终止(即main()
函数返回)时终止。它不等待其他非main
例程完成。
您启动了具有无限for
循环的第二个goroutine
,无法终止。因此,该循环将继续进行,直到main()
在并发的主goroutine中运行的函数返回为止。由于for
循环首先从接收jobs
,因此它将等待主goroutine将其关闭(此接收操作只能继续进行)。然后,主要goroutine希望从中接收信息done
,以便等到第二个goroutine在其上发送一个值。然后,主goroutine是“自由的”以随时终止。由于循环jobs
已关闭,因此运行循环的第2个goroutine可能会收到一个附加值,但随后的send
on done
会阻塞,因为不再有任何人从该接收(并且它没有缓冲)。
通常使用来完成从通道接收直到关闭的操作for range
,如果通道关闭则退出:
for j := range jobs {
fmt.Println("received: ", j)
done <- true
}
当然,这将在您的情况下造成死锁,因为永远不会到达循环主体,因为没有人发送任何东西jobs
,因此循环永远不会进入其主体以发送值,done
而这正是主要goroutine等待的。
关闭通道的意思是该通道将不再允许写入数据。这个方法可以让通道数据的接受端知道数据已经全部发送完成了。 package main import "fmt" // 在这个例子中,我们使用通道jobs在main函数所在的协程和一个数据 // 接收端所在的协程通信。当我们数据发送完成后,我们关闭jobs通道 func main() { jobs := make(chan int, 5) d
关闭RSS频道 停止内容之播放后,于显示频道一览时按下按钮。 提示 关闭RSS频道之行为并无法同时切断网络联机。若想切断联机,请将无线LAN按钮调整为OFF(关)。
问题内容: 在Java 8中,Stream类实现AutoCloseable。这意味着应显式关闭流实例。 我了解为什么文件处理程序和数据库连接是可关闭的。但是为什么要流? 问题答案: 我认为Stream的当前文档/ javadoc 非常清楚: 流具有BaseStream.close()方法并实现AutoCloseable,但是实际上几乎所有流实例在使用后都不需要关闭。通常,只有源是IO通道的流(例如
问题内容: 据我所知,默认情况下,转到频道的行为就像一个队列,先进先出。有什么方法可以改变它们以先进先出吗? 基本上,我正在执行搜索,并且想对内存限制使用DFS而不是BFS。 问题答案: 不,这是不可能的-通道始终是FIFO。您可以使用package 。
问题内容: 按照目前的情况,这个问题不适合我们的问答形式。我们希望答案会得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 8年前关闭。 我知道它还为时过早,但是我一直在尝试Go(Google的编程语言)及其在gedit中编写代码的烦人方式。 所以,我的问题是:您如何使用Go进行实验? 问题答案
我在看Tomcat的Java源代码,发现了这样的代码 它编译成功,而通常赋值应该是 为什么第一段代码编译成功?