Получить доступ

Что изменилось с переменной цикла в Go 1.22?

JuniorГорутины и каналыGo >=1.22
Ещё спрашивают так:
  • Почему все горутины в цикле печатали одно и то же значение?
Коротко

До Go 1.22 переменная цикла for i := ... была одна на весь цикл: замыкания и горутины, захватившие её, видели последнее значение. С Go 1.22 каждая итерация получает свою копию — классическая ошибка исчезла (для модулей с go 1.22 в go.mod).

  • Старое исправление: i := i внутри цикла или передача аргументом
  • Поведение зависит от версии в go.mod, а не компилятора
  • То же касается for k, v := range

А ещё В Python та же ловушка позднего связывания осталась

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Почему было так. Цикл переиспользовал одну переменную, меняя её значение. Замыкание захватывает переменную, а не значение; горутины стартуют позже, чем цикл успевает пройти дальше.

Изменение 1.22 (предложение Расса Кокса) сделало переменную на итерацию. Чтобы не сломать старый код, правило включается по версии языка в go.mod. Инструмент loopclosure в go vet ловил старую ошибку.

На собеседовании этот вопрос проверяет понимание замыканий и того, что горутина выполняется позже места запуска.

Пример

for _, url := range urls {
    go func() {
        fetch(url)     // Go 1.22+: своя url на итерацию
    }()                // до 1.22: все горутины могли взять последнюю
}

Что хотят услышать

  • Старое поведение и его причина.
  • Что изменилось и как включается.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем