[БЕЗ_ЗВУКА] В этом видео мы проговорим про горутины — одну из тех приятных вещей, которые делают вашу жизнь при разработке многопоточных программ в Go гораздо проще. Итак, рассмотрим для начала следующую программу. У нас есть цикл, который запускает каких-то worker'ов, которые делают какую-то работу. В данном случае работа — это просто напечатать что-то на экран. Сейчас я продемонстрирую, как это выглядит. Итак. Вот у нас запустился нулевой worker и что-то напечатал, вот первый worker что-то напечатал и так далее. Теперь, допустим, я хочу, чтобы эти worker'ы работали не последовательно, один за другим, а распараллелить их хочу. Для этого можно запустить их в разных горутинах. Как это делать? Очень просто. Для того чтобы запустить какую-либо функцию внутри отдельной горутины, нужно написать просто слово go. Вот так. Всё. Теперь в этом месте моя программа в этом цикле не заблокируется, пока worker не отработает, а сразу же перейдёт к следующему циклу, и в нём запустит следующую горутину. Но есть нюанс. В данном случае моя программа может выйти сразу же после окончания цикла, не дав поработать никаким горутинам. Поэтому я поставил fmt.Scanln (), чтобы она дожидалась вывода от меня. Как с этим работать, мы узнаем дальше, но сейчас давайте запустим и посмотрим, как наша программа отрабатывает в режиме горутин. Итак, отлично. Смотрите, сначала отработал, действительно, первый worker, успел урвать себе ресурсов, потом начался четвёртый, уже не первый, а четвёртый. Причём он отработал не до конца, а был прерван другими горутинами. То есть на самом деле это не последовательный запуск, это параллельный, просто выводится это всё последовательно. Итак. Теперь давайте попробуем симулировать работу, как будто бы мы пошли по сети и стоим ждём. В go есть возможность передать управление другой горутине. Это находится в пакете runtime, функция Goshed(), то есть вызвать планировщик задач. Смотрите, мы добавили всего одну строчку и посмотрим, как изменится вывод нашей программы. Запускаем. Если раньше наши горутины выполнялись в какой-то непонятной последовательности, при этом одна могла успеть выполнить либо много итераций, либо мало итераций, то сейчас она выполняет всего одну итерацию и передаёт управление другой горутине. Вот так это выглядит. То есть вывод уже совсем другой, не похож на предыдущий запуск. Но это всего лишь операция Goshed(). На самом деле, внутри функции Printf(), вот здесь, тоже может вызваться планировщик задач, и он тоже может передать работу другой горутине. При этом вы можете начать выполняться на одном системном треде, а продолжить выполняться на другом системном треде. То есть go не просто блокируется на каких-то там сетевых вызовах и передаёт управление дальше, нет. Планировщик может решить, что эта горутина уже много поработала, давайте передадим другой, то есть ваша программа не заблокируется просто в цикле. Да, она может заблокироваться в цикле, если вы там совершаете простые математические операции без вызова каких-либо функций. Также стоит отметить, что из горутины вы не можете вернуть никакое значение в основную программу, туда, где была вызвана эта горутина. Для этих целей используются каналы, про которые мы как раз и поговорим в следующем видео.