drio

Timeouts with context

This is a follow up of my first context post.

Another typical usage of context is to limit the duration of a particular process. The context construct provides two methods for that. First, WithTimeout() where we pass a context and the duration of the timer. The second option is WithDeadline() where we pass the exact Time.time we want the computation to stop. Both methods return the new context and a cancellation function we can use to cancel the context immediately.

Here is an example (with comments) where we have a goroutine that simulates a computation and another goroutine that implements the timeout.

package main

import (
	"context"
	"log"
	"time"
)

const (
	defaultTaskD int = 5
	defaultTO    int = 10
)

func main() {
	// compute the duration given the defaults
	taskDuration := time.Duration(defaultTaskD) * time.Second
	toDuration := time.Duration(defaultTO) * time.Second

	// Set a context with timeout
	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, toDuration)
	defer cancel()

	// We need a channel to send the results of our computations
	ch := make(chan int)
	// The goroutine for our task. Resturn 42 when done
	go func() {
		log.Printf("task starts running; taskDuration=%s timeout=%s", taskDuration, toDuration)
		time.Sleep(taskDuration)
		ch <- 42
	}()

	// If toDuration has passed, use the cancellation function
	go func() {
		time.Sleep(toDuration)
		cancel()
	}()

	// Wait for either a cancelation or the result of our computation
	select {
	case result := <-ch:
		log.Printf("task completed fine. result=%d\n", result)
	case <-ctx.Done():
		log.Println("task timed out")
	}
}