1. Природа горутин: концепция конкурентности на простых аналогиях
Природа горутин: концепция конкурентности на простых аналогиях
Представьте, что вы открыли кофейню. У вас есть один бариста, который принимает заказ, мелет зерна, взбивает молоко и отдает напиток. Пока он варит кофе одному гостю, очередь стоит. Если гость долго ищет карту для оплаты, бариста просто ждет. Это — последовательное выполнение. А теперь представьте, что бариста научился мгновенно переключаться: пока закипает чайник для первого клиента, он уже принимает заказ у второго. Кофейня не стала больше, бариста все еще один, но работа сдвинулась с мертвой точки. Это и есть магия горутин.
Конкурентность vs Параллелизм
Часто эти понятия путают, но для инженера Go различие критично. Конкурентность — это про структуру кода, а параллелизм — про исполнение.
> Конкурентность — это умение эффективно справляться с множеством дел одновременно. Параллелизм — это умение делать множество дел одновременно. > > Роб Пайк, соавтор языка Go
Представим стройку:
В Go мы пишем конкурентный код, разбивая задачу на горутины. Если у процессора вашего компьютера 8 ядер, рантайм Go может запустить их параллельно. Но даже на одном ядре горутины принесут пользу за счет эффективного переключения.
Почему не обычные потоки?
В большинстве языков программирования (Java, C++, Python) основной единицей параллелизма является поток операционной системы (OS Thread). У них есть три фундаментальных недостатка, которые Go успешно преодолевает:
| Характеристика | Поток ОС | Горутина (Go) | | :--- | :--- | :--- | | Размер стека | Фиксированный (~2 МБ) | Динамический (от 2 КБ) | | Управление | Ядро ОС | Рантайм Go | | Создание/Удаление | Дорого | Дешево | | Количество | Тысячи | Миллионы |
Легковесность как суперсила
Благодаря тому, что горутины потребляют так мало ресурсов, мы меняем сам подход к проектированию. В традиционных языках программист боится создавать лишние потоки и использует «пулы потоков» (Thread Pools). В Go мы придерживаемся правила: «Если задача логически независима — запусти ее в отдельной горутине».
Это позволяет нам масштабировать приложения до миллионов одновременных соединений. Например, на каждый входящий запрос в веб-сервере Go выделяется отдельная горутина. Это не перегружает систему, так как общая формула потребления памяти выглядит примерно так:
Где — количество активных горутин, а — размер стека (начинается с КБ).
Как горутины «сотрудничают»
Главный секрет эффективности Go кроется в кооперативном многозадачном режиме. Горутины не захватывают процессор навсегда. Они добровольно уступают место другим, когда:
Это похоже на слаженную работу на кухне ресторана: повар отходит от плиты, пока жарится стейк, чтобы нарезать салат, а не стоит над сковородкой до победного конца. В следующих главах мы разберем, как именно ключевое слово go превращает обычную функцию в такую независимую «кухонную единицу».