当我想要ctx超时时,我应该怎么做才能完全终止正在执行longRunningCalculation()的方法?
package main
import (
"context"
"log"
"time"
)
func longRunningCalculation(timeCost int) chan string {
result := make(chan string)
go func() {
time.Sleep(time.Second * (time.Duration(timeCost)))
log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
result <- "Done"
log.Println(timeCost)
}()
return result
}
func jobWithTimeout() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
select {
case <-ctx.Done():
log.Println(ctx.Err())
return
case result := <-longRunningCalculation(3):
log.Println(result)
}
}
func main() {
jobWithTimeout()
time.Sleep(time.Second * 5)
}
您期望看到什么?
2019/09/25 11:00:16上下文截止日期已超过
您看到了什么?
2019/09/25 11:00:16上下文截止日期已超过
2019/09/25 11:00:17还在做其他事情...
最佳答案
要在调用者的上下文超时时停止由longRunningCalculation
启动的goroutine,您需要将ctx
传递到longRunningCalculation
中,并显式处理上下文超时,与在jobWithTimeout
中所做的相同
这样操作还意味着,而不是调用time.Sleep
,time.Tick
将是一个更好的选择,因此这两个计时器都同时运行。像这样:
package main
import (
"context"
"log"
"time"
)
func longRunningCalculation(ctx context.Context, timeCost int) chan string {
result := make(chan string)
go func() {
calcDone := time.Tick(time.Second * time.Duration(timeCost))
log.Printf("entering select (longRunningCalculation)")
select {
case <-ctx.Done():
result <- "Caller timed out"
return
case <-calcDone:
log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
result <- "Done"
}
log.Println(timeCost)
}()
return result
}
func jobWithTimeout() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
result := longRunningCalculation(ctx, 3)
log.Printf("entering select (jobWithTimeout)")
select {
case <-ctx.Done():
log.Println(ctx.Err())
return
case res := <-result:
log.Println(res)
}
}
func main() {
jobWithTimeout()
}
关于go - ctx超时时,如何完全终止正在运行的go func()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58090804/