当ctx超时时,如何完全终止正在运行的go func()?

当ctx超时时,如何完全终止正在运行的go func()?,go,Go,当我需要ctx超时时,我应该怎么做才能完全终止正在执行longRunningCalculation()的方法 主程序包 进口( “上下文” “日志” “时间” ) func longRunningCalculation(时间成本整数)chan字符串{ 结果:=生成(chan字符串) go func(){ time.Sleep(time.Second*(time.Duration(timeCost))) log.Println(“仍在做其他事情…”)/即使超时,此goroutine仍在执行其他任务

当我需要ctx超时时,我应该怎么做才能完全终止正在执行longRunningCalculation()的方法

主程序包
进口(
“上下文”
“日志”
“时间”
)
func longRunningCalculation(时间成本整数)chan字符串{
结果:=生成(chan字符串)
go func(){
time.Sleep(time.Second*(time.Duration(timeCost)))
log.Println(“仍在做其他事情…”)/即使超时,此goroutine仍在执行其他任务。

结果要在调用方的上下文超时时停止由
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()
}
主程序包
进口(
“上下文”
“日志”
“时间”
)
func longRunningCalculation(ctx context.context,timeCost int)chan字符串{
结果:=生成(chan字符串)
go func(){
calcDone:=time.Tick(time.Second*time.Duration(timeCost))
log.Printf(“输入select(longRunningCalculation)”)
挑选{

如果您无法停止其他人的代码,您可以让代码(在适当的时候)询问“我现在应该停止吗?”来停止代码如果它得到一个答案,告诉它现在停止,它可以停止。如果它调用其他人的例行程序花费太长时间,你真的无能为力。这是真的,逻辑是复杂的。围棋没有魔力。如果你想让你的goroutine停止,你需要让它停止。这不仅仅是神奇地推断有一些相关的co在函数中使用上下文时,它应该始终是go标准中定义的第一个参数。为了能够中断
longRunningCalculation
,您必须中断它所做的工作,并检查

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()
}