Ответ
При использовании defer
внутри цикла, анонимная функция (замыкание) захватывает переменные из окружающей области видимости по ссылке, а не по значению. Это значит, что к моменту выполнения defer
(после завершения функции, содержащей цикл), будет использовано последнее значение переменной цикла.
Пример, демонстрирующий проблему:
package main
import (
"fmt"
)
func main() {
fmt.Println("Пример с проблемой:")
for i := 0; i < 3; i++ {
defer func() {
fmt.Println(i) // Всегда выведет 3 (последнее значение i после завершения цикла)
}()
}
fmt.Println("Конец цикла с defer")
}
// Вывод:
// Конец цикла с defer
// 3
// 3
// 3
Решение: Чтобы зафиксировать значение переменной для каждого вызова defer
, передайте переменную как аргумент анонимной функции. Это создаст копию значения для каждого замыкания.
package main
import (
"fmt"
)
func main() {
fmt.Println("Пример с решением:")
for i := 0; i < 3; i++ {
defer func(val int) {
fmt.Println(val) // Выведет 2, 1, 0 (в обратном порядке, как и положено для defer)
}(i) // Передаем текущее значение i как аргумент
}
fmt.Println("Конец цикла с defer")
}
// Вывод:
// Конец цикла с defer
// 2
// 1
// 0