🥊 Каналы vs Мьютексы: Главная ловушка философии Go — 19 августа 2026 г. в 07:38:47.423
🥊 Каналы vs Мьютексы: Главная ловушка философии Go Все знают самую знаменитую пословицу Роба Пайка: "Не общайтесь, разделяя память; разделяйте память, общаясь". Джун читает это и делает вывод: «Мьютексы - это устаревшее зло из C++, каналы - это тру-Go-вей!». И после этого пишет 50 строк кода с горутиной-координатором, select и каналами просто для того, чтобы безопасно инкрементировать счетчик просмотров или обновить мапу. Сеньор смотрит на это и грустит, потому что знает секрет: под капотом любого канала (в структуре hchan) лежит... обычный мьютекс. Использовать канал просто для защиты переменной - это как купить таксопарк, чтобы один раз съездить за хлебом. Давайте раз и навсегда проведем границу. 🛡 Когда берем Мьютексы (Состояние) Если ваша задача - защитить кусок данных (структуру, map, срез) от одновременного изменения, берите sync.Mutex или sync.RWMutex. - Это быстро: Взять свободный мьютекс - это дешевая атомарная операция (~15-20 наносекунд). Операции с каналами тяжелее, так как требуют работы с внутренними очередями и планировщиком. - Это просто: mu.Lock() и defer mu.Unlock(). Никаких рисков забыть закрыть канал и получить утечку горутины (Goroutine Leak). - Идеальный юзкейс: In-memory кэши, хранение сессий, счетчики внутри структур. 🚦 Когда берем Каналы (Оркестрация и Владение) Каналы нужны не для защиты данных, а для передачи владения (ownership) и управления потоком выполнения. - Передача эстафеты: Одна горутина скачала кусок данных, отдала его в канал и "забыла" про него. Вторая горутина забрала и начала парсить. - Оркестрация: Worker Pools, пайплайны (Fan-Out/Fan-In), о которых мы говорили раньше. - Таймауты и отмены: Вы не можете прервать ожидание mu.Lock() по таймауту. А вот конструкцию select { case <-ch: ... case <-time.After(1*time.Second): ... } - легко. ❌ Классический Антипаттерн: Создавать отдельную "горутину-хранитель", которая владеет мапой и слушает каналы chanGet и chanSet, чтобы отдавать и записывать значения. Это ад в отладке, работает медленнее мьютекса и требует написания кучи бойлерплейта. ✅ Золотое правило (одобрено разработчиками Go): - Используйте каналы для маршрутизации данных и контроля за горутинами. - Используйте мьютексы для защиты внутреннего состояния (state) ваших объектов. 🔥 Senior Tip: Атомики Если вам нужно защитить не сложную структуру, а просто инкрементировать счетчик или переключить флаг (число или bool), не берите ни мьютексы, ни каналы. Ваш выбор - пакет sync/atomic. Операция atomic.AddInt64 выполняется на уровне аппаратных инструкций процессора (CAS) и работает так быстро, что вы даже не увидите её в профайлере. #golang #concurrency #architecture #bestpractices #cleancode 👉 @golang_lib

