Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 Контент вільний від AI. Цей пост на 100% написаний людиною, як і все на моєму блозі. Насолоджуйтесь!

13.06.2023

Контексти в Golang

Як зупинити код у відповідь на зовнішній фактор? Один з механізмів відомий всім — то команда kill, якою можна зупинити цілий процес. Але, як зробити це всередині програми? Що робити, коли блок коду займає більше часу, ніж ми можемо чекати? Це реальні питання, які часто не мають гарної відповіді. Ось в Ruby, наприклад, є модуль Timeout, який наполегливо рекомендують не використовувати.

В Go питання зупинки процесів стає ще актуальнішим, оскільки створення одночасних процедур — типова повсякденна робота. Як зупинити всі ті горутіни, коли вони більше не потрібні? Можна накрутити (та я й крутив) додаткові канали для сигналізації. Зупиняємо сервіс — сигналізуємо горутінам.

…Паралельно з цим доводиться постійно передавати в різні бібліотечні функції якийсь “контекст”. Нащо він потрібен той контекст — не знаю. Добре що завжди можна створити новий на місці, наприклад функцією context.Background().

Та тільки нещодавно зрозумів, що контексти в Go і є той самий механізм зупинки коду у відповідь на зовнішній фактор. У контексту є метод ctx.Done(), який повертає канал, що буде закритий, якщо пора зупиняти код. Для перевірки використовується команда select. Це й треба використати замість самописних механізмів. Більше в документації.

Щоб створити власний корисний контекст, є відповідно функції context.WithCancel та context.WithTimeout. Особливо зручно те, що такі функції загортають контекст батьківського рівня, та успадковують закриття ще й від нього.

Для сигналів, про які я вже згадав, є signal.NotifyContext. Сервіс, який себе гарно поводить, має спиратись саме на цей контекст, щоб контрольовано зупинити всі свої компоненти.

Тепер ніяких більше context.Background().