Code Review
О чём этот блок
Писать конкурентный код — это половина работы. Вторая половина — читать чужой
код и находить в нём баги до того, как они доедут до прода. Гонки данных,
утечки горутин, aliasing переиспользуемого буфера, дописывание в общий слайс
без синхронизации — эти ошибки компилируются, проходят беглый просмотр и
взрываются только под нагрузкой или под -race. Этот блок переключает вас из
режима «автор» в режим «ревьюер»: вам дают рабочий на вид, но багованный код,
и задача — увидеть дефект, объяснить его и предложить починку.
Навык ревью конкурентного кода — один из самых ценных на собеседовании уровня middle+ и senior. Интервьюер проверяет не синтаксис, а вашу модель памяти: понимаете ли вы, где именно нарушен happens-before и почему запись из одной горутины может быть потеряна.
Что вы научитесь делать
- Находить data race глазами: общий слайс/мапа, в которые пишут несколько горутин без синхронизации.
- Распознавать aliasing буфера: слайс передан в фоновую горутину и тут же перезаписывается отправителем.
- Видеть утечки горутин: фоновый цикл, который никто не останавливает.
- Формулировать диагноз и минимальную корректную правку (мьютекс, копия
буфера,
done-канал, отмена). - Опираться на race detector и модель памяти как на инструменты доказательства.
Карта задач
- 21 · Сервис агрегации метрик — багованный батч-агрегатор: гонка данных,
утечка фоновой горутины и aliasing слайса-буфера, который одновременно
передан в
Saveи перезаписывается. Найти все три и починить. - 22 · Параллельный HTTP-воркер с кэшированием — воркеры дописывают в общий
слайс
resultsбез синхронизации: классическая гонка, падающая под-race. Локализовать и устранить.
Связанные главы учебника
- Утечки горутин и гонки — как находить гонки, race detector, goroutine leak, pprof.
- Модель памяти и happens-before — почему data race ≠ race condition и где именно нарушается видимость записей.
// Типичный баг ревью: запись в общий слайс из нескольких горутин.
go func(id int) {
results = append(results, fetch(id)) // ГОНКА: нет синхронизации
}(id)
// Лечение: mu.Lock()/Unlock() вокруг append или сбор через канал.