英文:
Can I force termination a goroutine without waiting for it to return?
问题
让我举个例子:
func WaitForStringOrTimeout() (string, error) {
my_channel := make(chan string)
go WaitForString(my_channel)
select {
case found_string := <-my_channel:
return found_string, nil
case <-time.After(15 * time.Minute):
return nil, errors.New("等待字符串超时")
}
}
在这个简单的例子中,我有一个名为WaitForString的函数,它会阻塞一段时间,最终可能返回一个字符串。我想用这段代码包装WaitForString函数,它要么返回相同的字符串,要么在超时时返回错误。
如果字符串很快被找到,那么是否还有一个带有15分钟睡眠语句的goroutine在运行,或者它会被垃圾回收?
如果超时发生并且字符串从未被找到,那么是否仍然有一个运行WaitForString的goroutine,即使没有其他例程可以观察它的输出?如果WaitForString分配了大量内存但从不返回会怎样?
有没有办法让WaitForString()意识到超时发生并放弃执行?
英文:
Let me use an example:
func WaitForStringOrTimeout() (string, error) {
my_channel := make(chan string)
go WaitForString(my_channel)
select {
case found_string := <-my_channel:
return found_string, nil
case <-time.After(15 * time.Minute):
return nil, errors.New("Timed out waiting for string")
}
}
In this simple example, I have some function WaitForString which blocks for awhile and eventually may return a string. I want to wrap WaitForString with this code which either returns the same string or times out with an error.
If a string is found quickly, is there still a goroutine running with a 15 minute sleep statement somewhere or is this garbage collected somehow?
If the timeout occurs and a string is never found, is there still a goroutine running WaitForString, even though there are no other routines that could observe it's output? What if WaitForString allocates a lot of memory but never returns?
Is there some way I can make WaitForString() become aware of the timeout occurring and give up?
答案1
得分: 3
通常情况下,没有办法停止另一个goroutine。有一个名为runtime.Goexit
的函数可以用来使当前的goroutine退出(即使在深层调用帧中调用),但没有办法使其他goroutine退出。
对于time
模块的特定情况,没有单独的goroutine处理每个计时器或定时器:相反,计时器由运行时集中管理,以便它可以知道下次何时需要唤醒。
虽然没有goroutine挂起,但通道和一个小的记录结构将保留15分钟。
如果这是一个问题,考虑使用time.NewTimer
而不是time.After
,并在返回时手动停止计时器。例如:
t := time.NewTimer(15 * time.Minute)
defer t.Stop()
select {
case found_string := <-my_channel:
return found_string, nil
case <-t.C:
return nil, errors.New("等待字符串超时")
}
time.After
对于精确的周期行为非常有用,而time.NewTimer
对于简单的超时操作也很好用。
英文:
In general, no there isn't a way to stop another goroutine. There is a runtime.Goexit
function that can be used to cause the current goroutine to exit (even if called from a deep call frame), but nothing to cause other goroutines to exit.
For the specific case of the time
module, there isn't a separate goroutine handling each timer or ticker: instead, timers are centrally managed by the runtime so it can tell when it next needs to wake up.
While there's no goroutine hanging around, the channel and a small bookkeeping struct will stick around for the 15 minutes.
If this is a problem, consider using time.NewTimer
instead of time.After
, and manually stop the timer when you return. For example:
t := time.NewTimer(15 * time.Minute)
defer t.Stop()
select {
case found_string := <-my_channel:
return found_string, nil
case <-t.C:
return nil, errors.New("Timed out waiting for string")
}
time.After
is really useful for exact periodic behaviour, whereas time.NewTimer
works fine for simple timeouts.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论