В чем разница между `context.TODO()` и `context.Background()`?

Ответ

И context.Background() и context.TODO() возвращают пустой, никогда не отменяемый контекст без значений. Разница между ними — семантическая, она служит подсказкой для разработчиков и статических анализаторов.

context.Background()

Это корневой, базовый контекст. Его следует использовать на самом верхнем уровне вашего приложения или процесса, когда вы создаете новый контекст "с нуля".

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

  • В функции main() или init() для запуска фоновых горутин.
  • В начале обработки входящего HTTP-запроса (хотя фреймворки обычно предоставляют свой контекст запроса).
  • В тестах, как родительский контекст для тестируемой функции.
func main() {
    // Создаем корневой контекст для всего приложения
    ctx := context.Background()

    // Запускаем фоновый сервис с этим контекстом
    go runMyService(ctx)
    // ...
}

context.TODO()

Это "заглушка" или временный контекст. Его используют, когда неясно, какой контекст передавать, или когда функция была написана без учета контекста, но в процессе рефакторинга его нужно добавить.

Использование context.TODO() — это сигнал для себя или коллег: "Здесь нужно разобраться с контекстом позже".

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

  • При рефакторинге старого кода, который еще не поддерживает context.
  • Когда вы вызываете функцию, требующую контекст, но у вас его пока нет (и это временное решение).
// Старая функция, которую мы хотим адаптировать
func someLegacyOperation() {
    // Мы еще не пробросили контекст до этого места,
    // поэтому временно используем TODO.
    ctx := context.TODO()

    // Вызываем новую функцию, которая требует контекст
    doSomethingNew(ctx, "some data")
}

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

Всегда старайтесь использовать context.Background() как отправную точку. Применяйте context.TODO() только как временную меру с намерением заменить его на правильный контекст в будущем. Некоторые линтеры могут специально помечать использование context.TODO() как предупреждение.

Ответ 18+ 🔞

А, ну вот, опять про эти ваши контексты! Сидишь такой, пишешь код, а тут тебе выкатывают context.Background() и context.TODO(). И вроде оба — пустые, никем не отменяемые, без всяких значений. Ну, типа, два близнеца, ёпта. Но нет, блядь, разница-то есть, и она не в технике, а в смысле, для нас, для распиздяев разработчиков!

context.Background()

Это типа царь-батюшка, коренной контекст, основа основ. Его ты юзаешь, когда начинаешь всё с чистого листа, на самом верху.

Куда его пихать:

  • В main() или init(), когда запускаешь какую-нибудь свою долбаную фоновую горутину.
  • В самом начале обработки HTTP-запроса (хотя там обычно фреймворк свой контекст уже подсовывает, хитрая жопа).
  • В тестах, когда надо что-то протестировать и с чего-то начать.
func main() {
    // Берёшь этот самый Background и поехали
    ctx := context.Background()

    // И кидаешь его, например, в свой сервис
    go runMyService(ctx)
    // ...
}

context.TODO()

А вот это, блядь, интересная штука! Это не контекст, а такая записка самому себе: «Чувак, тут разобраться надо, но щас не до этого, ёпта!».

Когда его впихивать:

  • Когда рефакторишь старый код, который про контексты слыхом не слыхивал, а менять всё лень.
  • Когда вызываешь функцию, которая уже требует контекст, а у тебя его пока как бы и нету — временно, на живую нитку.
// Допустим, есть у тебя древняя функция
func someLegacyOperation() {
    // Контекст сюда ещё не дотянулся, но функцию новую вызывать надо
    // Что делаешь? Правильно, втыкаешь TODO и живёшь с чувством легкой вины.
    ctx := context.TODO()

    // И вызываешь новую модуль, которая контекст жрёт
    doSomethingNew(ctx, "some data")
}

Так что в итоге, бля?

Всегда старайся начинать с Background() — это как белый холст. А TODO() — это такая заплатка, временная заглушка. Используешь её с мыслью «ладно, потом разберусь», а потом, конечно, забываешь. Некоторые линтеры, кстати, на это дело ругаться могут, мол, «опять ты, мудак, TODO оставил!». Так что лучше не злоупотреблять, а то так и будешь ходить с этим TODO как с писаной торбой.