好的SO警告我一个主观标题所以请让我解释一下.现在我正在看Go,我已经阅读了规范,观看了一些IO会谈,看起来很有趣,但我有一些问题.
我最喜欢的一个例子是这个select语句,它听取了来自"DoAfter()"或其他东西的频道,该频道将从现在开始在给定时间发送一些内容.
像这样的东西(这可能不会起作用,如果有的话也会伪造!)
to := Time.DoAfter(1000 * Time.MS)
select:
case <-to:
return nil //we timed out
case d := <-waitingfor:
return d
Run Code Online (Sandbox Code Playgroud)
假设我们正在等待的事情发生得非常快,所以这个函数返回并且不再听to
,DoAfter会发生什么?
我喜欢并知道你不应该测试频道
if(chanToSendTimeOutOn.isOpen()) {
chanToSendTimeOutOn<-true
}
Run Code Online (Sandbox Code Playgroud)
我喜欢通道同步位置,例如,上面的函数可能在isOpen()
测试后但在发送true之前返回.我真的反对测试,这避免了通道做什么 - 隐藏锁和诸如此类的东西.
我已经阅读了规范并看到了运行时恐慌和恢复,但在这个例子中我们在哪里恢复?等待发送超时的事情是一个例程还是各种各样的"对象"?我想象这个"对象"有一个排序列表,它列出了在给定时间之后必须发送的东西,并且它只是按正确的顺序将TimeAfter请求附加到队列并经历它.我不确定那里有什么机会实际恢复.
如果它产生了每个都有自己的定时器的go-routines(当然是由运行时管理,所以线程实际上不会阻塞时间)然后什么才有机会恢复?
我的问题的另一部分是关于频道的生命周期,我会想象它们被重新计算,那些能够读取的内容被重新计算,因此如果没有任何地方有可读的参考,它就会被销毁.我称之为确定性.对于"点对点"拓扑,你可以形成它,如果你坚持Go的"通过渠道发送东西,不要访问它"
所以这里例如,当想要超时的东西返回时to
,任何人都不再读取该频道.因此,现在的常规程序毫无意义,有没有办法让它在没有工作的情况下返回?
例:
文件读取过程已经用于defer
在文件完成时关闭文件,是否可以"感知"它应该发送的信息已关闭,因此返回时不再读取文件?
我也想知道为什么select语句是"非确定性的"如果第一种情况优先,如果第一种情况和第二种情况都准备好(对于非阻塞操作),我会非常喜欢它 - 我不会因此而谴责它,但有原因吗?这是什么实施的?
最后,如何安排常规课程?编译器是否会在每个指令中添加某种"让步",因此运行的线程将在不同的goroutine之间切换?我在哪里可以找到较低级别的信息?
我知道Go兜售"你根本不需要担心这个",但我想知道我写的东西实际隐藏(可能是C++的东西)以及原因.
Jam*_*dge 10
如果您写一个封闭的频道,您的节目将会出现恐慌(例如,请参阅http://play.golang.org/p/KU7MLrFQSx).您可能会捕获此错误recover
,但是在您不知道您正在写入的通道是否打开的情况下通常是程序中的错误的标志.通道的发送方负责关闭它,因此它应该知道当前状态.如果您在频道上发送了多个goroutines,那么他们应该在关闭频道时进行协调(例如,使用a sync.WaitGroup
).
在您的Time.DoAfter
假设中,它取决于通道是否被缓冲.如果它是一个无缓冲的通道,那么写入定时器通道的goroutine将会阻塞,直到有人从通道读取.如果这种情况从未发生过,那么在程序完成之前,goroutine将保持阻塞状态.如果频道已缓冲,则发送将立即完成.在任何人阅读之前,该频道可能被垃圾收集.
标准库time.After
以这种方式运行,返回带有一个槽缓冲区的通道.