Go в примери: Срокове

Задаването на срокове1 е важно за програми, които се свързват с външни източници на данни или по някакъв начин са обвързани с време за изпълнение. Осъществяването на краен срок в Го става лесно и изтънчено като съчетаем канали и select.


  1. timeout – уречен срок. Сроковете в Го биват осъществени чрез срочници, които са разгледани в по-нататъшен пример.
package main
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 канал.


  1. time.After създава нов срочник, който връща канала
    case <-time.After(3 * time.Second):
        fmt.Println("срок 2")
    }
}

Ако пуснем тази програма, ще видим, че при първото действие срокът изтича, а второто успява навреме.

$ go run timeouts.go
срок 1: 14:44:18.674
изход 2

Следващ пример: .