Timeouts

Тайм-ауты (Timeouts)|Timeouts #

// _Тайм-ауты_ важны для программ, которые подключаются
// к внешним ресурсам или которым необходимо ограничить
// время выполнения. Тайм-ауты в Go реализуются легко
// и элегантно благодаря каналам и `select`'ам.

package main

import (
	"fmt"
	"time"
)

func main() {

	// В нашем примере предположим, что мы выполняем внешний
	// вызов, который возвращает результат на канале `c1`
	// через 2с. Обратите внимание, что канал буферизован,
	// поэтому отправка в goroutine неблокирующая. Это
	// обычная схема предотвращения утечек горутин в случае,
	// если канал никогда не читается.ё
	c1 := make(chan string, 1)
	go func() {
		time.Sleep(2 * time.Second)
		c1 <- "result 1"
	}()

	// Вот `select`, реализующий тайм-аут. `res := <-c1`
	// ожидает результата, а `<-Time.After` ожидает
	// значения, которое будет отправлено после истечения
	// времени ожидания 1с. Поскольку `select` продолжает
	// работу с первым полученным запросом, мы возьмем
	// тайм-аут, если операция займет больше разрешенных 1с.
	select {
	case res := <-c1:
		fmt.Println(res)
	case <-time.After(1 * time.Second):
		fmt.Println("timeout 1")
	}

	// Если мы допустим время ожидания более 3с, то
	// получение от `c2` будет успешным, и мы распечатаем
	// результат.
	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")
	}
}
# Запуск этой программы показывает время ожидания
# первой и второй успешной операции.
$ go run timeouts.go 
timeout 1
result 2