登录
首页 >  Golang >  Go问答

每 N 秒运行一次函数,上下文超时

来源:stackoverflow

时间:2024-04-11 22:12:32 301浏览 收藏

最近发现不少小伙伴都对Golang很感兴趣,所以今天继续给大家介绍Golang相关的知识,本文《每 N 秒运行一次函数,上下文超时》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~

问题内容

我有一个关于调度“可取消”goroutine 的基本问题。

我想安排一个函数执行,每 3 秒一次。

该函数最多可能需要 5 秒。

如果它花费的时间超过 2999 毫秒,我想停止/终止它,以避免与下一个重叠。

我做错了:

func main() {
    fmt.Println("startProcessing")
    go startProcessing()

    time.Sleep(time.Second * 60)
    fmt.Println("endProcessing after 60s")
}

func startProcessing() {
    ticker := time.NewTicker(3 * time.Second)
    for _ = range ticker.C {
        ctx, _ := context.WithTimeout(context.Background(), (time.Second*3)-time.Millisecond)

        fmt.Println("start doSomething")
        doSomething(ctx)
    }
}

func doSomething(ctx context.Context) {
    executionTime := time.Duration(rand.Intn(5)+1) * time.Second

    for {
        select {
        case <-ctx.Done():
            fmt.Printf("timed out after %s\n", executionTime)
            return
        default:
            time.Sleep(executionTime)
            fmt.Printf("did something in %s\n", executionTime)
            return
        }
    }
}

这是我现在的输出:

开始处理 开始做某事 2秒内做了某事 开始做某事 3秒内做了某事 开始做某事 3秒内做了某事 开始做某事 5秒内做了某事 开始做某事 2秒内做了某事 ...

我想在 5s 之后读取 timed out,而不是在 5s 中读取 did 内容。


正确答案


您只需将 time.sleep(executiontime) 放在 select 之外,不需要 for 循环。我认为这在某种程度上是您想要的,但请注意这不是一个好的做法。因此,请查看下面的警告

func doSomething(ctx context.Context) {
    executionTime := time.Duration(rand.Intn(5)+1) * time.Second
    processed := make(chan int)

    go func() {
        time.Sleep(executionTime)
        processed <- 1
    }()

    select {
    case <-ctx.Done():
        fmt.Printf("timed out after %s\n", executionTime)
    case <-processed:
        fmt.Printf("did something in %s\n", executionTime)
    }
}

obs:我稍微改变了原来的答案。我们不能在执行过程中中断 goroutine。我们可以将长时间运行的任务委托给另一个 goroutine,并通过专用通道接收结果。

警告:如果您预计处理时间会超过截止日期,我不建议这样做,因为现在您将有一个泄漏的 goroutine。

到这里,我们也就讲完了《每 N 秒运行一次函数,上下文超时》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

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