我想在超时时停止执行goroutine。但似乎它对我不起作用。我正在使用iris
框架。
type Response struct {
data interface{}
status bool
}
func (s *CicService) Find() (interface{}, bool) {
ch := make(chan Response, 1)
go func() {
time.Sleep(10 * time.Second)
fmt.Println("test")
fmt.Println("test1")
ch <- Response{data: "data", status: true}
}()
select {
case <-ch:
fmt.Println("Read from ch")
res := <-ch
return res.data, res.status
case <-time.After(50 * time.Millisecond):
return "Timed out", false
}
}
输出:
Timed out
test
test1
预期产出:
Timed out
有人可以指出这里缺少什么吗?它确实超时但仍然运行goroutine来打印test
和test1
。我只想在超时后立即停止执行goroutine。
答案 0 :(得分:6)
没有好办法在执行过程中“中断”goroutine的执行。
Go使用并发的fork-join模型,这意味着你“fork”创建一个新的goroutine,然后在你到达“join point”之前无法控制goroutine的调度方式。连接点是多个goroutine之间的某种同步。例如在频道上发送值。
举一下你的具体例子,这一行:
ch <- Response{data: "data", status: true}
...将能够发送值,无论是什么,因为它是一个缓冲通道。但是你创建了超时:
case <-time.After(50 * time.Millisecond):
return "Timed out", false
这些超时位于频道的“接收者”或“阅读器”上,而“发件人”上的不是。如本答案顶部所述,如果不使用某些同步技术,就无法中断goroutine的执行。
因为超时是从频道“读取”的,所以没有什么可以阻止在频道上发送的goroutine的执行。
答案 1 :(得分:2)
控制 goroutine处理的最佳方式是context(std go library)。
你可以在goroutine中取消某些内容并停止执行而不会发生goroutine泄漏。
这里简单example,您的案例会超时取消。
ctx, cancel := context.WithCancel(context.Background())
ch := make(chan Response, 1)
go func() {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done():
fmt.Println("Canceled by timeout")
return
}
fmt.Println("test")
fmt.Println("test1")
ch <- Response{data: "data", status: true}
}()
select {
case <-ch:
fmt.Println("Read from ch")
case <-time.After(50 * time.Millisecond):
fmt.Println("Timed out")
cancel()
}
答案 2 :(得分:0)
您有一个gouroutine泄漏,您必须执行一些已完成的操作以在超时之前返回goroutine,如下所示:
plaintext