Материал проходит вычитку — возможны неточности.
Урок 67 из 118

Порядок и main-обрыв

Первая беда прилетела сразу: ночная утилита завершалась раньше фоновых загрузок, и часть файлов оставалась необработанной. Баг заметили только утром, когда отчёт за ночь оказался пустым.

Главная мысль

порядок исполнения горутин не гарантирован, а выход из main завершает процесс, не дожидаясь остальных горутин.

Порядок не гарантирован

Go

Горутины исполняются независимо, и в каком порядке они доберутся до своего кода — решает планировщик. Две горутины, запущенные подряд, могут выполниться в любом порядке, а их операции — перемешаться.

Нет неявного ожидания

Между горутинами нет отношения «одна подождала другую», пока ты сам его не выстроишь. Про способы синхронизации — каналы, WaitGroup, мьютексы — следующие модули.

Main — обрыв, а не ожидание

func main() {
    go func() {
        time.Sleep(time.Second)
        fmt.Println("не успею")
    }()
    // main возвращается — процесс завершается, горутина умирает
}

Строка «не успею» не напечатается. Это легко пропустить в коде, где горутины запускаются и про них забывают: на вид всё работает, а на деле часть работы отбрасывается на выходе. Утилита Миши именно так потеряла ночные загрузки. Дожидаться нужно явно — sync.WaitGroup.

В следующем уроке

Вы узнаете:

  • почему «не успею» может иногда напечататься
  • как sync.WaitGroup.Wait сравнивается с обычным ожиданием
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Гарантирован ли порядок вывода двух горутин, запущенных подряд?

Вопрос 2 из 3

В main запущена фоновая горутина со sleep 50 мс, и main сразу возвращается. Что произойдёт?

Вопрос 3 из 3

Две горутины печатают в цикле 1 и 2. Какой вывод возможен?

Итоги

Порядок горутин не определён; между ними нет неявного ожидания; выход из main обрывает всех. Синхронизация — всегда явная.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки