Go 1.22 и миграция
Команда решилась на миграцию на Go 1.22. Заодно пересмотрели старые «фиксы» логгера: часть из них больше не была нужна. Старый баг исчез вместе со старой семантикой.
с Go 1.22 переменная, объявленная в заголовке for через :=, своя на каждой итерации — включается это версией go.mod, для старых модулей код ведёт себя по-старому, и i:= i остаётся верным на обеих семантиках.
Новое поведение
На Go 1.22+ тот же код из прошлого урока даёт ожидаемый результат:
<!-- wp:code-run/run {"code":"var funcs []func() int\nfor i := 0; iВ for i:= 0; i < n; i++ первая итерация использует переменную из инициализации, а перед пост-инструкцией (i++) заводится свежая переменная для следующей итерации. Поэтому обычные идиомы вроде прохода по s[i] не изменились — разница видна только там, где i захватывается замыканием или у неё берут адрес. Важно: правило касается только переменных, объявленных в заголовке через :=. Заранее объявленная переменная, которой присваивают через = (var i int; for i = 0;...), остаётся одной на все итерации на любой версии языка.
Семантику включает go.mod
Изменение не включается просто новой версией компилятора. Поведение привязывается к версии языка, объявленной в go.mod: go 1.22 — новая семантика, go 1.21 и ниже — старая, даже если компилятор свежий. Это сделано, чтобы обновление тулчейна не меняло поведение работающего кода.
Что писать в общем коде
i:= i работает на обеих семантиках — явная копия переменной ничему не мешает. Если библиотека собирается под старыми версиями или вы просто не хотите зависеть от версии go.mod — ставьте i:= i. Для проверки старого поведения правку go.mod не обходят: надёжный способ — модуль с go 1.21. Флаг GOEXPERIMENT=loopvar направлен в другую сторону: он включает новую семантику (на Go 1.21 был её предпросмотром), а GOEXPERIMENT=noloopvar на современных тулчейнах не действует — откатом его не считают. Всё это — инструменты миграции, а не рабочий режим.
Вы узнаете:
- как переменная
rangeведёт себя в 1.22 - как проверить старое поведение через
GOEXPERIMENTи go.mod
Go 1.22: своя переменная на каждой итерации — но только объявленная в заголовке через := (заранее объявленная с = — общая); включается версией go.mod; i := i корректен везде.
10 000 ₽ · 60 минут · онлайн