01/03/2020 - GO
In this example we are going to run a goroutine and wait for it to finish its job. However, we only allow it to finish its job in maximum 3 seconds. If takes longer, we are going to force it to timeout. For that we are going to use context.WithTimeout feature.
package main
import (
"context"
"fmt"
"math/rand"
"time"
)
func main() {
fmt.Println(">>>>> BEGIN")
ctx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
// Cancel even if everything goes fine without an error to release resources.
defer cancel()
ch := make(chan int)
go doSomething(ch)
select {
case <-ctx.Done():
fmt.Println("TIMEOUT:", ctx.Err())
case t := <-ch:
fmt.Printf("JOB DONE in %d seconds\n", t)
}
fmt.Println(">>>>> END")
}
func doSomething(ch chan<- int) {
// Prevent picking up the same random number all the time for sleeping.
rand.Seed(time.Now().UnixNano())
// Pick a random number to simulate time it takes to finish the job.
delay := rand.Intn(5)
fmt.Printf("RUN: %d seconds\n", delay)
time.Sleep(time.Duration(delay) * time.Second)
ch<- delay
}
>>>>> BEGIN
RUN: 1 seconds
JOB DONE in 1 seconds
>>>>> END
>>>>> BEGIN
RUN: 4 seconds
TIMEOUT: context deadline exceeded
>>>>> END
>>>>> BEGIN
RUN: 5 seconds
TIMEOUT: context deadline exceeded
>>>>> END
>>>>> BEGIN
RUN: 3 seconds
JOB DONE in 3 seconds
>>>>> END