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