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