В чем разница между `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() как предупреждение.