Через какой тип реализуется механизм контекста в Go и каковы его основные методы?

Ответ

Механизм контекста в Go реализуется через интерфейс context.Context. Он предназначен для передачи сигналов отмены (cancellation), дедлайнов и других request-scoped значений через границы API и между горутинами.

Интерфейс context.Context определяет четыре метода:

type Context interface {
    // Deadline возвращает время, когда работа, связанная с этим контекстом,
    // должна быть отменена. ok=false, если дедлайн не установлен.
    Deadline() (deadline time.Time, ok bool)

    // Done возвращает канал, который закрывается, когда работа
    // должна быть отменена. Канал Done может вернуть nil.
    Done() <-chan struct{}

    // Err возвращает причину отмены контекста.
    // Возвращает context.Canceled или context.DeadlineExceeded.
    Err() error

    // Value возвращает значение, ассоциированное с ключом,
    // или nil, если такого ключа нет.
    Value(key any) any
}

Основные способы создания контекста:

  • context.Background(): Базовый, пустой контекст. Обычно используется в main() или на верхнем уровне обработки запроса.
  • context.TODO(): Используется как заглушка, когда неясно, какой контекст использовать.
  • context.WithCancel(parent): Создает контекст, который можно отменить вручную.
  • context.WithTimeout(parent, duration): Создает контекст, который отменится по истечении таймаута.
  • context.WithValue(parent, key, value): Добавляет в контекст пару ключ-значение.

Пример использования:

Функция, которая прекращает свою работу при отмене контекста.

func operation(ctx context.Context) {
    select {
    case <-time.After(5 * time.Second):
        fmt.Println("Операция завершена успешно")
    case <-ctx.Done(): // Канал закрылся, контекст отменен
        fmt.Println("Операция отменена:", ctx.Err())
    }
}

func main() {
    // Создаем контекст, который отменится через 2 секунды
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel() // Важно вызывать cancel для освобождения ресурсов

    operation(ctx) // Выведет: "Операция отменена: context deadline exceeded"
}