Пакет Go Context
Большинство Go-разработчиков используют context.Context, не понимая его сути. Вы встречаете его в HTTP-обработчиках, вызовах баз данных и методах SDK. Многие новички повсеместно передают context.Background().
Эта ошибка приводит к проблемам. Lambda-функция может зависнуть после истечения времени ожидания. Запрос к базе данных может продолжать выполняться даже после того, как пользователь отключился.
Context позволяет передавать сигналы отмены и дедлайны через ваш код. Он помогает ответить на три вопроса:
• Должна ли эта операция продолжать выполнение? • Когда эта операция должна завершиться? • Какие данные запроса передаются вместе с этим вызовом?
Интерфейс Context имеет четыре метода:
Deadline(): Возвращает время, когда контекст будет отменен.Done(): Возвращает канал, который закрывается при отмене контекста. Используйте его в операторахselect, чтобы остановить работу.Err(): Возвращает причину остановки контекста (DeadlineExceededилиCanceled).Value(): Извлекает данные, относящиеся к области видимости запроса, например, Trace ID.
Context работает как дерево. Вы начинаете с родительского контекста и создаете дочерние.
Корневые контексты:
context.Background(): Используйте его в начале программы.context.TODO(): Используйте его в качестве временной заглушки во время рефакторинга.
Дочерние контексты:
context.WithCancel(): Позволяет остановить работу вручную.context.WithTimeout(): Останавливает работу через определенный промежуток времени.context.WithDeadline(): Останавливает работу в определенное время.context.WithValue(): Передает метаданные, такие как ID пользователя.
Важное правило: Всегда вызывайте функцию cancel. Используйте defer cancel() сразу после создания дочернего контекста. Если вы пропустите этот шаг, возникнут утечки памяти.
Лучшие практики:
- Передавайте
contextпервым аргументом в функции. - Не храните
contextв структурах. - Используйте
context.WithValueтолько для метаданных, а не для зависимостей, таких как клиенты баз данных. - Проверяйте
ctx.Err()внутри длинных циклов, чтобы выйти из них заранее. - Используйте пользовательские типы для ключей контекста, чтобы избежать коллизий.
Когда родительский контекст отменяется, все его дочерние контексты отменяются автоматически. Это позволяет легко остановить всю цепочку операций во всей вашей системе.