0Pricing
Go Academy · Урок

WithDeadline и WithValue

Абсолютные крайние сроки и передача значений в области запроса

«WithDeadline и WithValue» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

context.WithDeadline

WithDeadline создаёт контекст, который отменяется в определённый момент времени. Если у родительского контекста уже установлен более ранний крайний срок, приоритет имеет срок родительского контекста.

deadline := time.Now().Add(10 * time.Second)
ctx, cancel := context.WithDeadline(parent, deadline)
defer cancel()

WithTimeout и WithDeadline

WithTimeout(parent, d) эквивалентен WithDeadline(parent, time.Now().Add(d)). Используйте WithDeadline, когда у Вас есть абсолютный момент истечения срока действия, например из входящего заголовка RPC.

Чтение крайнего срока

Проверяйте крайний срок любого контекста с помощью ctx.Deadline(). Логическое значение указывает, существует ли крайний срок.

if deadline, ok := ctx.Deadline(); ok {
    fmt.Println("expires at:", deadline)
}

context.WithValue

WithValue добавляет в контекст пару «ключ—значение». Код на последующих этапах извлекает её с помощью ctx.Value(key).

type ctxKey string
const userKey ctxKey = "user"

ctx := context.WithValue(parent, userKey, currentUser)

func getUser(ctx context.Context) *User {
    u, _ := ctx.Value(userKey).(*User)
    return u
}

Предотвращение конфликтов ключей

Используйте неэкспортируемый тип, специфичный для пакета, в качестве ключей, чтобы предотвратить конфликты между пакетами. Никогда не используйте встроенные типы (string, int) напрямую как ключи контекста.

// Bad: string key can collide
ctx = context.WithValue(ctx, "user", u)
// Good: package-scoped type
type userKeyType struct{}
ctx = context.WithValue(ctx, userKeyType{}, u)

Что хранить в контексте

Храните только значения, относящиеся к области действия запроса и пересекающие границы API: идентификаторы трассировки, токены Auth, идентификаторы запросов. Не храните необязательные аргументы функций или изменяемое состояние.

Производительность WithValue

ctx.Value выполняет линейный поиск вверх по цепочке контекстов. Избегайте хранения большого количества значений в одном контексте; несколько значений объединяйте в одной структуре.

type RequestMeta struct {
    UserID  int
    TraceID string
}
type metaKey struct{}
ctx = context.WithValue(ctx, metaKey{}, RequestMeta{...})

Передача значений через промежуточное ПО

Промежуточное ПО HTTP — стандартное место для добавления метаданных запроса в контекст и их извлечения в обработчиках:

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        user := authenticate(r)
        ctx := context.WithValue(r.Context(), userKey, user)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

r.WithContext

Заменяйте контекст HTTP-запроса с помощью r.WithContext(ctx). Это создаёт поверхностную копию запроса с новым контекстом, не изменяя исходный.

Передача крайнего срока

Когда шлюз задаёт крайний срок в контексте и передаёт запрос дальше, все службы, принимающие этот контекст, автоматически соблюдают крайний срок без явной логики тайм-аута.

Цепочка контекстов

Каждый WithValue, WithCancel или WithTimeout оборачивает родительский контекст в новый узел. ctx.Value проходит по цепочке, пока не найдёт ключ или не достигнет корневого контекста, возвращающего nil.

Быстрая проверка

Почему ключи контекста должны быть неэкспортируемыми типами, специфичными для пакета?

Итоги: WithDeadline и WithValue

Основные положения:

  • WithDeadline отменяет контекст в абсолютный момент времени, а WithTimeout задаёт относительный срок
  • ctx.Deadline() считывает крайний срок
  • Используйте WithValue для метаданных, относящихся к области действия запроса, и типизированные неэкспортируемые ключи
  • Объединяйте несколько значений в структуре, чтобы уменьшить глубину цепочки

Часто задаваемые вопросы

Урок «WithDeadline и WithValue» бесплатный?

Да — полный текст урока «WithDeadline и WithValue» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «WithDeadline и WithValue»?

Абсолютные крайние сроки и передача значений в области запроса Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «WithDeadline и WithValue»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Зачем нужен context.Context
  2. WithCancel и WithTimeout
  3. WithDeadline и WithValue
  4. Контекст в HTTP- и вызовах к базе данных
← Назад к Go Academy