Собственно, уже сейчас новое поведение можно включить с помощью специального флага. Суть изменения заключается в том, что раньше происходил захват переменной в цикле. Если вы не знакомы с этим явлением, то вот вам пример:
var (
a = []int{1, 2, 3}
b []*int
)
for _, n := range a {
b = append(b, &n)
}
for _, n := range b {
fmt.Println(*n)
}
Что будет выведено программой? Конечно же,
3 3 3, а не 1 2 3. Так происходит, потому что та самая переменная n в цикле для экономии памяти не создаётся заново на каждой итерации, а по сути просто меняет свой указатель с одного места памяти на другое. Из-за чего и наблюдаем такой эффект. Это неочевидно для новичков и про это легко забыть. Чтобы этой проблемы избежать, обычно использовали некрасивый, но действенный трюк: внутри тела цикла объявляется новая переменная n, которой присваивается n: for _, n := range a {
n := n
…
}
Что? Да!
Чтобы не кошмарить новых адептов, авторы языка и вводят новое поведение для циклов — такое, какое вы ожидали бы без захвата переменной.
С одной стороны это нарушение обещания авторов языка о сохранении обратной совместимости. С другой стороны эта особенность циклов и правда фрустрирует и сложно представить ситуацию, когда это пригодилось бы. Т.е. обратная совместимость вроде и сломана, но перестанет работать корректно критически маленькая доля программ, которые написаны как-то по-наркомански и скомпилированы через Go 1.22.
Такие дела ¯\_(ツ)_/¯
❤️ • ютуб • бусти • патреон • платный канал