В чем разница между context.WithTimeout и context.WithDeadline?

Ответ

Оба метода пакета context создают контекст, который автоматически отменяется по истечении времени. Ключевое различие — в способе задания этого времени.

  1. context.WithTimeout(parent, duration)

    • Принимает относительный интервал времени (time.Duration).
    • Удобен, когда нужно ограничить операцию простым таймаутом: "выполнять не дольше 2 секунд".
    // Контекст отменится через 2 секунды после его создания
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel() // Важно всегда вызывать cancel()
  2. context.WithDeadline(parent, time)

    • Принимает абсолютный момент времени (time.Time).
    • Идеален, когда есть общий дедлайн для цепочки операций: "все дочерние операции должны завершиться к 17:00".
    // Рассчитываем дедлайн: сейчас + 2 секунды
    deadline := time.Now().Add(2 * time.Second)
    ctx, cancel := context.WithDeadline(context.Background(), deadline)
    defer cancel()

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

  • WithTimeout — самый частый выбор для простых таймаутов (HTTP-запросы, запросы к БД).
  • WithDeadline — полезен при пробрасывании общего дедлайна через несколько сервисов или функций. Если функция получает контекст с дедлайном, она может использовать его для своих дочерних операций.

Важный момент: под капотом context.WithTimeout(parent, duration) является просто удобной обёрткой и вызывает context.WithDeadline(parent, time.Now().Add(duration)).

Ответ 18+ 🔞

Так, слушай, вот объясняю про эти контексты в Go, как бабушке на лавочке. Есть два способа заставить твой код не тупить вечность, а вовремя послать всё нахуй.

Первый — context.WithTimeout(parent, duration) Это как поставить таймер на духовке. Говоришь: «Эй, пирожки, у вас есть ровно две минуты, а потом я вас выкидываю, даже если вы сырые внутри». Передаёшь просто интервал — 2*time.Second. Удобно, быстро, мозги не надо ломать.

// Через две секунды — пиздец, отмена, всем спасибо.
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // Это, блядь, не забывай, а то память потечёт!

Второй — context.WithDeadline(parent, time) А это уже планёрка у начальства. Тебе говорят: «К пяти часам, сука, отчёт на столе!». И не важно, сколько времени сейчас — ты должен успеть к конкретному моменту. Передаёшь абсолютное время, time.Time.

// Рассчитываешь этот ебучий дедлайн: сейчас + 2 секунды.
deadline := time.Now().Add(2 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()

Так когда чем пользоваться, ёпта?

  • WithTimeout — твой ежедневный инструмент, как отвертка. Запрос к базе, вызов API — везде, где нужно просто сказать «больше двух секунд не жду, пошёл нахуй».
  • WithDeadline — когда есть общий, ебаный, сквозной дедлайн на целую цепочку вызовов. Получил его сверху — пробросил вниз, чтобы все дочерние функции тоже знали, что к пяти часам всё летит в тартарары.

И главный секрет, от которого сам отъебешься: внутри WithTimeout — это просто обёртка, которая вызывает WithDeadline, прибавляя к текущему времени твой интервал. Так что, по сути, разница только в том, как тебе удобнее думать: «через сколько» или «к какому часу».

Вот и вся магия, ебать мои старые костыли. Главное — cancel() не забудь, а то будет тебе вечная утечка, хуй потом найдёшь.