Go в примери: Видът Context

В предишен пример разгледахме създаването на прост HTTP сървър. HTTP сървърите са полезни за показване ползата от context.Context за управление на откази (от започнати действия). Един обект от вида context.Context носи в себе си крайни срокове, сигнали за отказване и други свойства в обхвата на една заявка през границите на взаимодействия (API) и гозадачи. (Сиреч може да бъде споделян между тях (бел. прев.)).

package main
import (
    "fmt"
    "net/http"
    "time"
)
func hello(w http.ResponseWriter, req *http.Request) {

Обект от вида context.Context бива създаден при всяка заявка от net/http и може да бъде достъпен чрез метода Context() на обект от вида *http.Request.

    ctx := req.Context()
    fmt.Println("сървър: пуснахме обработчика 'здрасти'.")
    defer fmt.Println("сървър: спряхме обработчика 'здрасти'.")

Изчакваме няколко секунди преди да изпратим отговор на клиента. Така симулираме, че сървърът върши някаква работа. Докато работи, наглеждаме канала, връщан от Done() за знак, че работата трябва да бъде прекъсната и да се излезе от обработчика незабавно.

    select {
    case <-time.After(10 * time.Second):
        fmt.Fprintf(w, "здрасти\n")
    case <-ctx.Done():

Методът Err() на контекста връща грешка, която обяснява защо каналът, върнат от Done() е затворен.

        err := ctx.Err()
        fmt.Println("сървър:", err)
        internalError := http.StatusInternalServerError
        http.Error(w, err.Error(), internalError)
    }
}
func main() {

Както преди, записваме, че нашата функция ще обработва заявки към пътя “/hello”, и започваме да обслужваме заявки.

    http.HandleFunc("/hello", hello)
    http.ListenAndServe(":8090", nil)
}

Пускаме сървъра на заден план.

$ go run context.go &

Правим заявка към /hello и малко след това натискаме Ctrl+C, и така обозначаваме отказ от заявката.

$ curl localhost:8090/hello
сървър: пуснахме обработчика 'здрасти'.
^Cсървър: context canceled
сървър: спряхме обработчика 'здрасти'.

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