Go Gopher How to Go

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Go is clean and simple using select and time.After.

💡 Key Points

  • Timeouts are essential for programs that interact with external resources.
  • select with a time.After channel is the idiomatic way to implement timeouts in Go.
  • time.After waits for the duration to elapse and then sends the current time on the returned channel.
  • A timeout occurs if the time.After case is selected before the main operation's channel receives a value.
  • This pattern prevents goroutines from blocking indefinitely.

Timeout Example

This example shows how to use select with time.After to implement a timeout on a channel operation.

package main

import (
	"fmt"
	"time"
)

func main() {
	c1 := make(chan string, 1)
	go func() {
		time.Sleep(2 * time.Second)
		c1 <- "result 1"
	}()

	select {
	case res := <-c1:
		fmt.Println(res)
	case <-time.After(1 * time.Second):
		fmt.Println("timeout 1")
	}

	c2 := make(chan string, 1)
	go func() {
		time.Sleep(2 * time.Second)
		c2 <- "result 2"
	}()
	select {
	case res := <-c2:
		fmt.Println(res)
	case <-time.After(3 * time.Second):
		fmt.Println("timeout 2")
	}
}
Output:
timeout 1
result 2

Timeout Pattern

ComponentRoleExample
Operation ChannelThe channel for the primary operation.c1 := make(chan string, 1)
time.AfterCreates a channel that fires after a duration.&lt;-time.After(1 * time.Second)
selectWaits on both channels.select { case res := &lt;-c1: ... case &lt;-time.After(...): ... }