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

在 Go 中,我想要time.Sleep一段时间(例如在重试之间等待),但如果上下文被取消(不仅是从截止日期,而且是手动),我想快速返回。

这样做的正确或最佳方法是什么?谢谢!


Smart猫小萌
浏览 143回答 3
3回答

翻阅古今

您可以使用select它来实现:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time"&nbsp; &nbsp; "context")func main() {&nbsp; &nbsp; fmt.Println("Hello, playground")&nbsp; &nbsp; ctx, cancel := context.WithCancel(context.Background())&nbsp; &nbsp; defer cancel()&nbsp; &nbsp; go func(){&nbsp; &nbsp; &nbsp; &nbsp; t := time.Now()&nbsp; &nbsp; &nbsp; &nbsp; select{&nbsp; &nbsp; &nbsp; &nbsp; case <-ctx.Done(): //context cancelled&nbsp; &nbsp; &nbsp; &nbsp; case <-time.After(2 * time.Second): //timeout&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("here after: %v\n", time.Since(t))&nbsp; &nbsp; }()&nbsp; &nbsp; cancel() //cancel manually, comment out to see timeout kick in&nbsp; &nbsp; time.Sleep(3 * time.Second)&nbsp; &nbsp; fmt.Println("done")}这是Go-playground 链接

茅侃侃

select您可以像其他人提到的那样使用;但是,其他答案有一个错误,因为timer.After()如果不清理就会泄漏内存。func SleepWithContext(ctx context.Context, d time.Duration) {&nbsp; &nbsp; timer := time.NewTimer(d)&nbsp; &nbsp; select {&nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; &nbsp; &nbsp; if !timer.Stop() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <-timer.C&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; case <-timer.C:&nbsp; &nbsp; }}

拉丁的传说

这是一个sleepContext您可以用来代替的函数time.Sleep:func sleepContext(ctx context.Context, delay time.Duration) {&nbsp; &nbsp; select {&nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; case <-time.After(delay):&nbsp; &nbsp; }}以及一些示例用法(Go Playground 上的完整可运行代码):func main() {&nbsp; &nbsp; ctx := context.Background()&nbsp; &nbsp; fmt.Println(time.Now())&nbsp; &nbsp; sleepContext(ctx, 1*time.Second)&nbsp; &nbsp; fmt.Println(time.Now())&nbsp; &nbsp; ctxTimeout, cancel := context.WithTimeout(ctx, 500*time.Millisecond)&nbsp; &nbsp; sleepContext(ctxTimeout, 1*time.Second)&nbsp; &nbsp; cancel()&nbsp; &nbsp; fmt.Println(time.Now())}
打开App,查看更多内容
随时随地看视频慕课网APP