💬 Что такое захват переменной в Go?



Захват переменной в Go происходит в случаях, когда функция или другая конструкция использует переменные, объявленные за пределами своей собственной области видимости (скоупа).



Во вложенном скоупе есть возможность обращаться к переменным, объявленным в скоупе выше (но не наоборот). Обращение к переменным из вышестоящего скоупа — и есть их захват. Например:



func main() {

var funcs []func()



for i := 0; i < 3; i++ {

funcs = append(funcs, func() {

fmt.Println(i)

})

}



for _, f := range funcs {

f()

}

}





Каждая функция в funcs захватывает переменную i. Однако, поскольку они захватывают саму переменную, а не ее значение на момент создания функции, все функции при вызове будут выводить одно и то же значение — значение i после завершения цикла, то есть 3.



Чтобы избежать этой проблемы и захватить текущее значение переменной внутри цикла, можно использовать локальную переменную внутри цикла:



func main() {

var funcs []func()



for i := 0; i < 3; i++ {

i := i // создаем локальную переменную

funcs = append(funcs, func() {

fmt.Println(i)

})

}



for _, f := range funcs {

f()

}

}



Результат:

0

1

2