При работе с анонимными функциями в Go возникает так называемый "эффект захвата переменной" или "захват by value". Это означает, что анонимная функция не захватывает саму переменную, а копирует ее значение на момент создания функции.
Давайте рассмотрим пример:
package main import "fmt" func main() { numbers := []int{1, 2, 3, 4, 5} funcs := make([]func(), 0) for _, num := range numbers { funcs = append(funcs, func() { fmt.Println(num) }) } for _, f := range funcs { f() } }
В данном примере у нас есть срез чисел numbers
и срез функций funcs
. Мы итерируемся по числам, и для каждого числа добавляем в срез функцию, которая просто выводит это число.
Однако, если мы запустим этот код, то увидим, что в выводе будет только число 5
, повторяющееся пять раз. Это происходит потому, что анонимная функция, добавляемая в funcs
, захватывает переменную num
по значению, а не по ссылке.
Когда мы вызываем эти анонимные функции во втором цикле, они уже имеют доступ только к одной и той же копии переменной num
, которая остается равной последнему значению из итерации цикла.
Один из способов решить эту проблему - это использовать временную переменную внутри цикла, которая будет скопирована в каждую анонимную функцию:
package main import "fmt" func main() { numbers := []int{1, 2, 3, 4, 5} funcs := make([]func(), 0) for _, num := range numbers { numCopy := num funcs = append(funcs, func() { fmt.Println(numCopy) }) } for _, f := range funcs { f() } }
Теперь, когда мы вызываем каждую из функций во втором цикле, каждая из них будет использовать свою собственную копию переменной numCopy
, и результатом будет вывод всех чисел из среза numbers
.
В заключение, анонимные функции в Go захватывают переменные по значению, что может привести к неожиданным результатам, особенно в случаях, когда используются в циклах. Чтобы избежать этой проблемы, можно использовать временную переменную внутри цикла, чтобы гарантировать правильное захватывание значения.