#tip #go #beginner
Использование ссылки на переменную итератора цикла
В Go переменная итератора цикла — это единственная переменная, которая принимает разные значения на каждой итерации цикла. Это очень эффективно, но может привести к непреднамеренному поведению при неправильном использовании. Смотрите пример слева, который выдаст неожиданные результаты:
На каждой итерации мы добавляем адрес
Новый вывод программы — это то, что ожидалось:
Строка
Хотя этот пример может показаться несколько очевидным, такое же неожиданное поведение может быть более скрытым в некоторых других случаях. Например, переменная цикла может быть массивом, а ссылка может быть срезом (пример справа). В результате получаем:
Использование ссылки на переменную итератора цикла
В Go переменная итератора цикла — это единственная переменная, которая принимает разные значения на каждой итерации цикла. Это очень эффективно, но может привести к непреднамеренному поведению при неправильном использовании. Смотрите пример слева, который выдаст неожиданные результаты:
Values: 3 3 3
Addresses: 0x40e020 0x40e020 0x40e020На каждой итерации мы добавляем адрес
i к срезу out, но поскольку это одна и та же переменная, мы добавляем тот же адрес, который в итоге содержит последнее значение, присвоенное i. Одно из решений — скопировать переменную цикла в новую переменную:for i := 0; i < 3; i++ {
i := i
out = append(out, &i)
}Новый вывод программы — это то, что ожидалось:
Values: 0 1 2
Addresses: 0x40e024 0x40e028 0x40e032Строка
i := i копирует переменную цикла i в новую переменную, ограниченную блоком тела цикла for, также называемым i. Адрес новой переменной — это тот, который добавляется к массиву. В каждой итерации цикла создается новая переменная.Хотя этот пример может показаться несколько очевидным, такое же неожиданное поведение может быть более скрытым в некоторых других случаях. Например, переменная цикла может быть массивом, а ссылка может быть срезом (пример справа). В результате получаем:
Values: [[3] [3] [3]]👍22