// _Тайм-ауты_ важны для программ, которые подключаются // к внешним ресурсам или которым необходимо ограничить // время выполнения. Тайм-ауты в 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") } }