Почему вывод в цикле с горутинами в Go не гарантирован по порядку
Что проверяют
Понимаете ли вы, что конкурентность это не порядок. Проверяют знание того, что без явной синхронизации между горутинами нет отношения «происходит раньше», и умеете ли вы восстановить порядок там, где он действительно нужен.
Как отвечать
Запуск горутины только ставит её в очередь планировщика и сразу возвращает управление. Планировщик раскладывает горутины по потокам операционной системы, одновременно исполняются не более чем GOMAXPROCS штук, переключение происходит на блокировках и на вытеснении длинных участков. Никакого отношения порядка между горутинами при этом не возникает, пока вы его не создали каналом, мьютексом, группой ожидания или атомарной операцией. Поэтому вывод меняется от запуска к запуску и зависит от загрузки машины.
Отдельно проговорите, что группа ожидания даёт ровно одну гарантию: к моменту продолжения все горутины завершились. Про очерёдность между ними она не говорит ничего.
Если порядок нужен, его строят явно:
- каждая горутина пишет результат в свою ячейку заранее выделенного среза, а печать идёт после ожидания, последовательно;
- результаты уходят в канал, а печатает одна горутина-потребитель;
- цепочка каналов, где каждая ждёт сигнал предыдущей. Параллелизма тут почти не остаётся, и это честный признак, что задача последовательная.
Где спотыкаются
Объясняют перемешанный вывод гонкой внутри печати. Запись в стандартный вывод синхронизирована, строки не рвутся на части. Недетерминирован именно момент, когда горутина получает процессор.
Захватывают переменную цикла вместо передачи её значением. Пока переменная одна на весь цикл, все горутины видят последнее значение. Начиная с Go 1.22 переменная своя на каждой итерации, но старый код читают до сих пор, и передача аргументом остаётся безопасной привычкой.
Вызывают добавление счётчика внутри самой горутины, а не до запуска: ожидание успевает пройти раньше. Рядом обычно живёт настоящая гонка, когда результаты пишут в общую карту без мьютекса. Ловится запуском тестов с детектором гонок.