Какова область видимости переменной, объявленной в заголовке обычного for-цикла?
Переменная, объявленная в инициализаторе обычного for-цикла, доступна в условии цикла, пост-операции и теле цикла. Её область видимости заканчивается в конце всего оператора for, поэтому после цикла это имя недоступно.
Go использует лексические области видимости: доступность имени определяется структурой исходного кода, а не моментом выполнения. Для переменной цикла это позволяет ограничить временное состояние самим циклом и не загрязнять внешнюю область лишними именами.
Такой подход также уменьшает риск случайно использовать счётчик после завершения цикла или конфликтовать с переменной с тем же именем во внешнем блоке.
Если переменная объявлена прямо в заголовке цикла, попытка обратиться к ней после for приводит к ошибке компиляции. Если же переменная была объявлена раньше, заголовок цикла может только присвоить ей значение, и тогда она останется доступной после цикла.
Неверное понимание этого правила часто приводит к ошибкам при переносе счётчика, индекса или признака завершения цикла за пределы его тела.
В объявлении вида:
i видна во всех частях данного оператора for: в условии i < 3, в пост-операции i++ и внутри тела. После закрывающей фигурной скобки область видимости заканчивается.
Ключевое различие — между объявлением и присваиванием. Вариант с := создаёт новую переменную в области видимости цикла, а вариант с = использует уже существующую переменную:
Вложенный блок может затенить переменную цикла новым объявлением. Это не изменяет саму переменную цикла: после завершения вложенного блока снова видна внешняя переменная.
Допустим, после цикла требуется использовать итоговый индекс. Можно объявить индекс в заголовке цикла — это безопаснее с точки зрения ограничения области видимости, но итоговое значение будет недоступно после цикла. Можно объявить индекс заранее — тогда он доступен после цикла, однако увеличивается область его жизни и риск случайного использования в другом коде.
Если итоговый индекс действительно нужен после завершения, выбирают предварительное объявление и присваивание через =. Если он нужен только для обхода, предпочтительнее := в заголовке: компилятор сам ограничит область видимости и поможет избежать ошибочного обращения к переменной позже.
Да. Область видимости начинается после завершения объявления в инициализаторе, поэтому переменная доступна в условии, пост-операции и теле цикла. Практически это и позволяет использовать один счётчик во всех частях конструкции for.
Объявление через := в заголовке цикла создаст новую переменную, которая затенит внешнюю на время действия for. Изменения этой переменной не изменяют внешнюю. При использовании = новая переменная не создаётся: изменяется внешняя переменная, если она доступна и совместима по типу.
Да, если функция или замыкание создаётся в теле цикла, оно может захватить переменную цикла, поскольку та находится в его области видимости. Однако конкретное поведение при накоплении таких замыканий зависит от правил объявления переменной цикла и версии Go; для предсказуемого кода обычно явно создают отдельную переменную на итерацию, когда замыкания должны сохранить разные значения.