Как остановить или обновить горутину на вызывающей стороне в Go
Что проверяют
Знаете ли вы, что горутину нельзя убить снаружи: в Go нет аналога Thread.stop, остановка всегда кооперативная. Интервьюер хочет услышать, как горутина узнаёт о сигнале, как вызывающая сторона дожидается её завершения и как не получить утечку. Следом обычно спрашивают, что будет, если горутина висит на чтении из сети.
Как отвечать
Базовые механизмы:
context.Context: вызывающая сторона создаётctx, cancel := context.WithCancel(parent)илиWithTimeout, передаётctxв горутину и вызываетcancel(). Горутина вselectслушает<-ctx.Done()и выходит, причину отдаётctx.Err(), аcontext.WithCancelCauseпозволяет передать свою ошибку;- закрытие канала:
close(done)наchan struct{}будит всех читателей сразу, это широковещательный сигнал. Закрывает канал один владелец, повторныйcloseвызывает панику; - обновление без остановки: в тот же
selectдобавляется каналupdates chan Config, и горутина меняет параметры между итерациями. Если конфиг только читается, подходитatomic.Pointer[Config]: вызывающая сторона делаетStore, горутинаLoad; - ожидание завершения: сигнал отмены не значит, что горутина уже вышла. Дождаться помогает
sync.WaitGroup, аerrgroup.WithContextизgolang.org/x/syncещё и отменяет остальных при первой ошибке.
Отмену видит только код, который её проверяет. Блокирующие вызовы должны принимать контекст: http.NewRequestWithContext, db.QueryContext, для сырых соединений conn.SetDeadline. Вместо time.Sleep в цикле используют time.NewTicker или таймер внутри select, иначе горутина реагирует только после пробуждения.
Где спотыкаются
Пишут select с веткой default и time.Sleep внутри. Горутина либо крутит процессор впустую, либо узнаёт об отмене с задержкой на весь сон.
Забывают вызвать cancel. Ресурсы контекста живут до отмены родителя, go vet об этом предупреждает, но не во всех случаях. Правило простое: defer cancel() сразу после создания.
Считают, что после cancel() работа закончена, и сразу закрывают соединение с базой или выходят из main. Без ожидания через WaitGroup горутина может ещё писать в уже закрытый ресурс.