Ответ
И 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 как с писаной торбой.