Демонстрация отмены в Golang с использованием context.Context

GolangGolangBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Этот лабораторный практикум旨在演示context.Context在Golang中用于控制取消操作的用法。Context跨API边界和goroutine携带截止日期、取消信号及其他请求范围的值。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/NetworkingGroup(["Networking"]) go/NetworkingGroup -.-> go/context("Context") subgraph Lab Skills go/context -.-> lab-15466{{"Демонстрация отмены в Golang с использованием context.Context"}} end

Контекст

Функция hello имитирует некоторую работу, выполняемую сервером, ожидая несколько секунд перед отправкой ответа клиенту. Во время работы следите за каналом Done() контекста на сигнал о том, что мы должны отменить работу и вернуться как можно скорее.

  • Версия Golang 1.13 или выше.
## Запустите сервер в фоновом режиме.
$ go run context-in-http-servers.go &

## Имитируйте запрос клиента к `/hello`, нажав
## Ctrl+C вскоре после запуска для сигнализации
## отмены.
$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended

Ниже представлен полный код:

// В предыдущем примере мы рассматривали настройку простого
// [HTTP-сервера](http-servers). HTTP-сервера полезны для
// демонстрации использования `context.Context` для
// управления отменой. `Context` переносит даты окончания,
// сигналы отмены и другие значения, относящиеся к запросу,
// через границы API и goroutine.
package main

import (
	"fmt"
	"net/http"
	"time"
)

func hello(w http.ResponseWriter, req *http.Request) {

	// `context.Context` создается для каждого запроса
	// механизмом `net/http` и доступен с помощью
	// метода `Context()`.
	ctx := req.Context()
	fmt.Println("server: hello handler started")
	defer fmt.Println("server: hello handler ended")

	// Подождите несколько секунд перед отправкой ответа
	// клиенту. Это может имитировать некоторую работу,
	// выполняемую сервером. Во время работы следите за
	// каналом `Done()` контекста на сигнал о том, что мы
	// должны отменить работу и вернуться как можно скорее.
	select {
	case <-time.After(10 * time.Second):
		fmt.Fprintf(w, "hello\n")
	case <-ctx.Done():
		// Метод `Err()` контекста возвращает ошибку,
		// которая объясняет, почему канал `Done()` был
		// закрыт.
		err := ctx.Err()
		fmt.Println("server:", err)
		internalError := http.StatusInternalServerError
		http.Error(w, err.Error(), internalError)
	}
}

func main() {

	// Как и раньше, мы регистрируем наш обработчик на
	// маршруте "/hello" и начинаем обслуживание.
	http.HandleFunc("/hello", hello)
	http.ListenAndServe(":8090", nil)
}

Резюме

В этом лабораторном практикуме мы узнали, как использовать context.Context для управления отменой в Golang. Создав Context с таймаутом и передав его в функцию, мы можем убедиться, что функция вернется как можно скорее, если превышен таймаут.