Задаването на срокове1 е важно за
програми, които се свързват с външни източници на данни
или по някакъв начин са обвързани с време за
изпълнение. Осъществяването на краен срок в Го става
лесно и изтънчено като съчетаем канали и select.
import (
"fmt"
"time"
)
func main() {
За целите на нашия пример, нека си представим, че
извикваме външна програма, която връща стойност
по канал с име c1 след две секунди.
Забележете, че каналът е складиращ, така че
изпращането не спъва изпълнението (не блокира).
Това е обичаен начин за предотврятване на утечки,
причинени от гозадачи, в случай че никога не
прочетем данни от канала.
c1 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c1 <- "изход 1"
}()
Ето го нашия избор (select), чрез който
осъществяваме краен срок. Чрез изявлението res :=
<-c1 очакваме стойността да дойде по канала и я
записваме в res, а с израза <-time.After
обозначаваме, че очакваме стойността да дойде до
една секунда. Тази функция After връща текущото
време по създаден в себе си канал за пренос на
стойности от вида time.Time, след подадена
продължителност (time.Duration).
Понеже select обработва веднага първата получена
(готова) стойност, ще попаднем в случая (case)
<-time.After(1 * time.Second), ако данните не
пристигнат в уреченото време - до една секунда.
select {
case res := <-c1:
fmt.Println(res)
case сега := <-time.After(1 * time.Second):
fmt.Println("срок 1:",
сега.Format(`15:04:05.000`))
}
Ако укажем по-дълъг срок (3 секунди), тогава ще
успеем да получим данните по канала c2 преди
изтичането на срока и ще изведем данните на екрана.
c2 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c2 <- "изход 2"
}()
select {
case res := <-c2:
fmt.Println(res)
Сега просто не правим нищо с полученото време по
създадения в time.After1 канал.
time.After създава нов срочник, който връща канала case <-time.After(3 * time.Second):
fmt.Println("срок 2")
}
}
Ако пуснем тази програма, ще видим, че при първото действие срокът изтича, а второто успява навреме.
$ go run timeouts.go
срок 1: 14:44:18.674
изход 2
Следващ пример: Неспъващи действия с канали.