为了账号安全,请及时绑定邮箱和手机立即绑定

如何在响应式上下文取消的情况下入睡?

如何在响应式上下文取消的情况下入睡?

Go
Smart猫小萌 2023-06-12 17:23:51
在 Go 中,我想要time.Sleep一段时间(例如在重试之间等待),但如果上下文被取消(不仅是从截止日期,而且是手动),我想快速返回。这样做的正确或最佳方法是什么?谢谢!
查看完整描述

3 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

您可以使用select它来实现:


package main


import (

    "fmt"

    "time"

    "context"

)


func main() {

    fmt.Println("Hello, playground")

    ctx, cancel := context.WithCancel(context.Background())

    defer cancel()

    go func(){

        t := time.Now()

        select{

        case <-ctx.Done(): //context cancelled

        case <-time.After(2 * time.Second): //timeout

        }

        fmt.Printf("here after: %v\n", time.Since(t))

    }()


    cancel() //cancel manually, comment out to see timeout kick in

    time.Sleep(3 * time.Second)

    fmt.Println("done")


}

这是Go-playground 链接


查看完整回答
反对 回复 2023-06-12
?
茅侃侃

TA贡献1842条经验 获得超21个赞

select您可以像其他人提到的那样使用;但是,其他答案有一个错误,因为timer.After()如果不清理就会泄漏内存。


func SleepWithContext(ctx context.Context, d time.Duration) {

    timer := time.NewTimer(d)

    select {

    case <-ctx.Done():

        if !timer.Stop() {

            <-timer.C

        }

    case <-timer.C:

    }

}


查看完整回答
反对 回复 2023-06-12
?
拉丁的传说

TA贡献1789条经验 获得超8个赞

这是一个sleepContext您可以用来代替的函数time.Sleep:


func sleepContext(ctx context.Context, delay time.Duration) {

    select {

    case <-ctx.Done():

    case <-time.After(delay):

    }

}

以及一些示例用法(Go Playground 上的完整可运行代码):


func main() {

    ctx := context.Background()


    fmt.Println(time.Now())

    sleepContext(ctx, 1*time.Second)

    fmt.Println(time.Now())


    ctxTimeout, cancel := context.WithTimeout(ctx, 500*time.Millisecond)

    sleepContext(ctxTimeout, 1*time.Second)

    cancel()

    fmt.Println(time.Now())

}


查看完整回答
反对 回复 2023-06-12
  • 3 回答
  • 0 关注
  • 141 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信