Встречается на 25% собеседований по Go

Что такое context в Go

Пакет context в Go предоставляет стандартный механизм для управления временем жизни операций, их отменой и передачи контекстно-зависимых данных. Он является ключевым инструментом для разработки надёжных конкурентных программ, позволяя контролировать выполнение горутин и предотвращать утечки ресурсов.

Как это работает

context позволяет создавать цепочки контекстов, где родительский контекст может отменять дочерние. Основные возможности:

  • Управление временем жизни: задание дедлайнов или таймаутов для операций (например, HTTP-запросов, обращения к БД).
  • Отмена операций: отмена родительского контекста автоматически отменяет все дочерние, что удобно для распределённых систем.
  • Передача данных: через WithValue можно передавать запрос-специфичные данные (идентификаторы, токены), хотя это не основное назначение.

Основные функции

ФункцияОписание
context.Background()Пустой контекст, корень всех контекстов.
context.WithCancel(parent)Создаёт дочерний контекст с функцией cancel, которая отменяет его и всех потомков.
context.WithDeadline(parent, time)Отменяется автоматически в указанное время.
context.WithTimeout(parent, duration)Отменяется через указанный интервал времени.
context.WithValue(parent, key, val)Добавляет пару ключ-значение для передачи данных.

Пример

go
package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    // Создаём контекст с таймаутом 2 секунды
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel() // вызываем cancel при выходе из main

    go func() {
        select {
        case <-time.After(1 * time.Second):
            fmt.Println("operation succeeded")
        case <-ctx.Done():
            fmt.Println("operation canceled")
        }
    }()

    time.Sleep(3 * time.Second) // ждём дольше таймаута
}

В этом примере горутина ждёт 1 секунду, но контекст отменяется через 2 секунды. Так как операция завершается раньше, выводится "operation succeeded". Если бы операция длилась дольше таймаута, контекст бы отменился, и мы увидели бы "operation canceled".

Подводные камни

  • Всегда вызывайте cancel: даже если контекст с таймаутом, defer cancel() предотвращает утечку ресурсов.
  • Не храните контекст в структурах: передавайте его первым аргументом в функции.
  • Не используйте WithValue для передачи необязательных параметров: это делает код менее читаемым.
  • Не игнорируйте ctx.Done(): если функция блокируется, она должна реагировать на отмену.

Когда использовать

  • При работе с HTTP-серверами: каждый запрос получает свой контекст.
  • При вызовах к внешним сервисам или БД: ограничение времени ожидания.
  • При запуске горутин, которые должны останавливаться по сигналу.

Коротко

  • context управляет отменой, таймаутами и передачей данных.
  • Основные функции: WithCancel, WithDeadline, WithTimeout, WithValue.
  • Всегда вызывайте cancel, чтобы избежать утечек.
  • Передавайте контекст первым аргументом в функции.
  • Следите за ctx.Done() в длительных операциях.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы