Ответ
Замыкание (closure) — это функция, которая «запоминает» и имеет доступ к переменным из своей лексической области видимости, даже когда она выполняется вне этой области. В Go анонимные функции часто выступают в роли замыканий.
Ключевые особенности:
- Захват переменных: Функция захватывает переменные из внешней области, к которым она обращается.
- Время жизни: Захваченные переменные продолжают существовать до тех пор, пока на них ссылается замыкание, даже если внешняя функция уже завершила свою работу.
- Изменение переменных: Замыкание может изменять значение захваченных переменных.
Простой пример:
func greeter() func(string) {
prefix := "Hello, "
// Эта анонимная функция является замыканием
return func(name string) {
fmt.Println(prefix + name) // Использует переменную 'prefix' из внешней функции
}
}
func main() {
g := greeter()
g("Alice") // Выведет: Hello, Alice
g("Bob") // Выведет: Hello, Bob
}
Частая ошибка (захват переменной цикла):
Замыкание захватывает ссылку на переменную, а не ее значение в момент создания. Это важно помнить при работе с циклами и горутинами.
// Неправильно: все горутины выведут "10", т.к. i к моменту их запуска уже будет равно 10
for i := 0; i < 10; i++ {
go func() {
fmt.Println(i)
}()
}
// Правильно: передаем значение i в замыкание как аргумент
for i := 0; i < 10; i++ {
go func(val int) {
fmt.Println(val)
}(i)
}