Closure
В этом примере на Go демонстрируется замыкание (closure) — функция, которая запоминает окружение, в котором она была создана.
1. Функция intSeq()
создаёт замыкание
func intSeq() func() int {
i := 0 // Локальная переменная внутри intSeq
return func() int { // Возвращаемая анонимная функция
i++ // Замыкание "видит" переменную i
return i
}
}
i := 0
— это локальная переменная внутриintSeq
.- Возвращаемая функция
func() int
“замыкается” вокругi
, то есть запоминает её и может изменять.
2. Создаём экземпляр замыкания
nextInt := intSeq() // Переменная nextInt теперь — функция
- При вызове
intSeq()
:- Создаётся переменная
i = 0
. - Возвращается функция-замыкание, которая удерживает ссылку на
i
.
- Создаётся переменная
3. Вызов nextInt()
изменяет состояние i
p(nextInt()) // Выведет: === 1 ===
p(nextInt()) // Выведет: === 2 ===
p(nextInt()) // Выведет: === 3 ===
- Каждый вызов
nextInt()
:- Увеличивает
i
на 1 (i++
). - Возвращает новое значение.
- Увеличивает
i
сохраняется между вызовами — это и есть “запомненное окружение”.
4. Новое замыкание — новый экземпляр i
newInts := intSeq() // Создаётся новый экземпляр замыкания
p(newInts()) // Выведет: === 1 === (не 4!)
newInts
— это новое замыкание с собственной переменнойi = 0
.- Оно не связано с
nextInt
— их состояния (i
) независимы.
Итог: как работает замыкание
- Запоминает окружение (переменные, например
i
), даже после выхода из внешней функции. - Сохраняет состояние между вызовами (
i
увеличивается). - Каждое новое замыкание создаёт свой экземпляр переменных.
Это полезно для:
- Генераторов (как в примере).
- Callback-функций с сохранением состояния.
- Инкапсуляции данных (аналог private переменных в ООП).
Пример в JavaScript (для сравнения):
function intSeq() {
let i = 0;
return () => ++i;
}
Работает аналогично!