Ответ
Пакет context в Go предназначен для управления отменой операций, установкой дедлайнов и передачей данных, специфичных для запроса, через границы API и между горутинами.
Существует несколько основных способов создания и использования контекстов:
-
context.Background()— это корневой, пустой контекст. Он никогда не отменяется, не имеет значений и дедлайнов. Обычно используется вmain(), при инициализации или в тестах как отправная точка для создания других контекстов.ctx := context.Background() -
context.TODO()— также пустой контекст, который следует использовать, когда вы не уверены, какой контекст применить, или если функция будет доработана для его получения в будущем. Служит как временная "заглушка".ctx := context.TODO() -
context.WithCancel(parent)— создает дочерний контекст, который можно отменить вручную. Возвращает контекст и функциюcancel(). Вызов этой функции отменяет данный контекст и все производные от него.ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Важно всегда вызывать cancel, чтобы освободить ресурсы -
context.WithTimeout(parent, timeout)— создает контекст, который автоматически отменяется по истечении заданногоtimeout.ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() -
context.WithDeadline(parent, time)— похож наWithTimeout, но отмена происходит в конкретный момент времени (time), а не через интервал.deadline := time.Now().Add(2 * time.Hour) ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel() -
context.WithValue(parent, key, value)— позволяет передавать данные внутри контекста. Важно: этот способ следует использовать с осторожностью, в основном для передачи опциональных, сквозных данных (например, ID трассировки, токен аутентификации), а не обязательных параметров функции, так как это делает API неявным.type key string const userIDKey key = "userID" ctx := context.WithValue(context.Background(), userIDKey, 123)
Ответ 18+ 🔞
Ну, слушай, смотри, вот есть у нас в Go эта штука — context. Ну, типа, такая палочка-выручалочка, чтобы управлять всякой асинхронной хуйней: отменять операции, ставить им дедлайны и таскать за собой какие-то данные, как мешок с картошкой, через все границы функций и горутин.
Создать его можно по-разному, вот смотри, я тебе сейчас разложу, как блядь на блюдечке.
1. context.Background() — это, типа, корень всего, пустой контекст-дед. Его никогда не отменят, в нём нихуя нет — ни значений, ни сроков. Используешь его обычно в самом начале, в main() или в тестах, как стартовую точку.
ctx := context.Background()
2. context.TODO() — это его брат-близнец, тоже пустой. Но его юзают, когда ты пока не придумал, какой контекст сюда впихнуть, или функция ещё в разработке. Типа временная заглушка, чтобы компилятор не ругался.
ctx := context.TODO()
3. context.WithCancel(parent) — вот тут уже начинается магия. Берёшь родительский контекст и делаешь из него ребёнка, которого можно отменить ручками. Возвращает он контекст и функцию cancel(). Вызвал cancel() — и всё, пиздец, этот контекст и все его дети отменены.
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Это, блядь, обязательно, а то ресурсы потекут
4. context.WithTimeout(parent, timeout) — а это для нетерпеливых. Создаёшь контекст, который сам отвалится через заданный промежуток времени. Удобно, когда не хочешь ждать ответа от какого-нибудь тормозного сервиса до скончания веков.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
5. context.WithDeadline(parent, time) — почти то же самое, но тут ты указываешь конкретный момент, когда всему придёт пиздец. Не "через 5 секунд", а "ровно в 14:00, хуй с ним".
deadline := time.Now().Add(2 * time.Hour)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
6. context.WithValue(parent, key, value) — о, это моё любимое! Позволяет запихнуть в контекст любые данные, как в сейф. Но, ёпта, будь осторожен! Не превращай его в помойку для всех параметров функции. Используй только для сквозных вещей, вроде ID запроса или токена, а то потом сам себя не поймёшь.
type key string
const userIDKey key = "userID"
ctx := context.WithValue(context.Background(), userIDKey, 123)
Вот так вот, коротко и без воды. Главное — не забывай вызывать cancel() и не пихай в контекст всё подряд, а то получишь пиздопроебибну с неявными зависимостями.