> Куда попадает функция при вызове go в Go? В какую очередь? (Go)

Уровень: middle · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: InDrive

Стек: Go

> Пример ответа

Короткий ответ

При вызове go func() функция попадает не в очередь, а в планировщик Go runtime. Она становится горутиной и помещается в локальную очередь (local run queue) текущего P (processor), либо в глобальную очередь (global run queue), если локальная переполнена. Дальше планировщик распределяет горутины по доступным потокам ОС (M) в рамках модели GMP.

Подробное объяснение

В Go используется модель планирования GMP:

  • G - горутина (goroutine), единица работы.
  • M - поток операционной системы (machine), который выполняет горутины.
  • P - логический процессор (processor), контекст выполнения, который связывает G и M.

При вызове go f() runtime создаёт новую горутину G и пытается поместить её в локальную очередь текущего P. Локальная очередь - это кольцевой буфер фиксированного размера (обычно 256 элементов). Если локальная очередь заполнена, горутина отправляется в глобальную очередь - общий список, защищённый мьютексом.

Планировщик работает по принципу work stealing: когда у P заканчиваются горутины в локальной очереди, он пытается украсть половину горутин из локальной очереди другого P, и только потом обращается к глобальной очереди. Глобальная очередь также периодически проверяется каждым P (каждые 61 тик планировщика), чтобы избежать голодания горутин, попавших в неё.

Важно: это не классическая очередь задач в смысле FIFO. Планировщик может переставлять горутины, вытеснять их (preemption) и менять порядок выполнения. Горутина не ждёт своей очереди пассивно - она либо выполняется, либо заблокирована на канале, мьютексе или системном вызове.

На практике

Для backend-разработчика важно понимать, что:

  • Количество одновременно выполняющихся горутин ограничено числом P (по умолчанию GOMAXPROCS, обычно равно числу ядер CPU).
  • Остальные горутины ждут в очередях, но это ожидание не блокирует поток ОС - M может переключиться на другую горутину.
  • При системных вызовах (например, чтение из сети) P отсоединяется от M, и M блокируется, а P переходит к другому M - это позволяет не простаивать ядрам.
  • Не стоит создавать миллионы горутин бездумно: каждая занимает минимум 2 КБ стека, плюс накладные расходы на планирование.

Пример кода

GO
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(2) // 2 P, значит до 2 горутин выполняются одновременно
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
fmt.Println("goroutine", n)
}(i)
}
wg.Wait()
}

Здесь 10 горутин создаются и попадают в очереди планировщика. При двух P одновременно выполняются только две, остальные ждут в локальных или глобальной очередях.

Как отвечать на собеседовании

Начни с короткого ответа: "функция становится горутиной и попадает в планировщик, в локальную очередь P или глобальную". Затем раскрой модель GMP, упомяни work stealing и вытеснение. Если спросят про очередь - подчеркни, что это не простая FIFO, а сложная система с приоритетами и перераспределением. Хорошо добавить пример с GOMAXPROCS и объяснить, почему горутины не блокируют потоки ОС.

Что проверяет интервьюер

Интервьюер проверяет:

  • Понимание модели GMP, а не поверхностное знание "горутины лёгкие".
  • Знание разницы между локальной и глобальной очередями.
  • Понимание work stealing и почему он нужен.
  • Осознание, что планировщик - это не очередь задач, а сложный механизм с вытеснением и блокировками.
  • Умение объяснить, как горутины взаимодействуют с системными вызовами.

Типичные ошибки

  • Ответ "функция попадает в очередь задач" без упоминания планировщика и P.
  • Утверждение, что горутины выполняются строго в порядке создания - это не так.
  • Путаница между очередью горутин и очередью сообщений в каналах.
  • Игнорирование глобальной очереди и work stealing.
  • Утверждение, что количество горутин ограничено числом ядер - на самом деле ограничено только памятью, одновременно выполняющихся - числом P.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью