In Go, I want to time.Sleep
for some time (e.g. waiting between retries), but want to return quickly if the context gets canceled (not just from a deadline, but also manually).
What is the right or best way to do that? Thanks!
<-ctx. Done() once the Done channel is closed, the case <-ctx. Done(): is selected. Once this happens, the function should abandon work and prepare to return. That means you should close any open pipes, free resources and return form the function.
Request. Context method returns a context associated with the request. That context is canceled if the HTTP client disconnects or cancels the HTTP request (possible in HTTP/2).
You can use select
to acheive this:
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")
}
Here is the Go-playground link
Here is a sleepContext
function that you can use instead of time.Sleep
:
func sleepContext(ctx context.Context, delay time.Duration) {
select {
case <-ctx.Done():
case <-time.After(delay):
}
}
And some sample usage (full runnable code on the 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())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With