登录
首页 >  Golang >  Go问答

如何在Go中正确处理ctx超时并终止正在运行的goroutine?

来源:stackoverflow

时间:2024-02-24 12:30:28 303浏览 收藏

亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《如何在Go中正确处理ctx超时并终止正在运行的goroutine?》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下,希望所有认真读完的童鞋们,都有实质性的提高。

问题内容

当我想要 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.tick 将是更好的选择,而不是调用 time.sleep,因此两个计时器同时运行。就像这样:

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超时并终止正在运行的goroutine?》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>