Go Academy · Урок

defer, анонимные функции и замыкания

Отложенные вызовы и значения функций

Урок 4 из 412 шагов

«defer, анонимные функции и замыкания» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Отложенное выполнение

defer планирует вызов функции на момент возврата из окружающей функции — независимо от способа возврата (обычного, из-за ошибки или паники):

func readFile(path string) {
    f, err := os.Open(path)
    if err != nil { return }
    defer f.Close() // runs when readFile returns
    // read from f...
}

Порядок выполнения отложенных вызовов

Отложенные вызовы помещаются в стек и выполняются в порядке LIFO (последним добавлен — первым выполнен):

func main() {
    defer fmt.Println("third")
    defer fmt.Println("second")
    defer fmt.Println("first")
    // Output: first, second, third
}

defer для освобождения ресурсов

defer — идиоматичный способ гарантировать освобождение ресурсов:

  • Разблокировать мьютекс после его блокировки
  • Закрыть файл после его открытия
  • Зафиксировать транзакцию базы данных или отменить её
  • Сообщить WaitGroup о завершении после добавления задачи

defer с аргументами

Аргументы отложенного вызова вычисляются немедленно в момент вызова defer, а не при выполнении отложенного вызова:

x := 10
defer fmt.Println(x) // prints 10, not 20
x = 20
fmt.Println(x)       // prints 20

Анонимные функции

Анонимные функции (литералы функций) определяются непосредственно в коде и не имеют имени:

double := func(n int) int {
    return n * 2
}
fmt.Println(double(5)) // 10

// Immediately invoked:
result := func(a, b int) int { return a + b }(3, 4)

Замыкания

Замыкание — это функция, которая захватывает переменные из окружающей области видимости:

func makeCounter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

ctr := makeCounter()
fmt.Println(ctr(), ctr(), ctr()) // 1 2 3

Особенность захвата переменных замыканиями в циклах

Замыкания захватывают переменные по ссылке — это распространённая ошибка в циклах с горутинами:

for i := 0; i < 3; i++ {
    i := i // create a new variable per iteration
    go func() { fmt.Println(i) }()
}

defer с именованными возвратами

Отложенные функции могут изменять именованные возвращаемые значения — это удобно для добавления пояснений к ошибкам:

func doWork() (err error) {
    defer func() {
        if err != nil {
            err = fmt.Errorf("doWork: %w", err)
        }
    }()
    return riskyOp()
}

Функциональные шаблоны с замыканиями

Замыкания позволяют применять функциональные шаблоны, например мемоизацию:

func memoize(f func(int) int) func(int) int {
    cache := map[int]int{}
    return func(n int) int {
        if v, ok := cache[n]; ok {
            return v
        }
        v := f(n)
        cache[n] = v
        return v
    }
}

Замыкания как промежуточное ПО

Замыкания — основа промежуточного ПО в HTTP-серверах Go: они оборачивают обработчик и добавляют поведение вокруг него:

func withLogging(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        log.Printf("%s %s", r.Method, r.URL)
        next(w, r)
    }
}

Быстрая проверка

Когда вычисляются аргументы отложенного вызова функции?

Итоги: отложенное выполнение, замыкания и анонимные функции

Эти возможности делают код Go выразительным и безопасным:

  • defer гарантирует освобождение ресурсов при выходе из функции — в порядке LIFO
  • Аргументы defer вычисляются немедленно
  • Анонимные функции можно присваивать переменным или вызывать непосредственно в коде
  • Замыкания захватывают окружающие переменные по ссылке
  • Следите за ошибками захвата переменных цикла в горутинах

Следующий курс: массивы, срезы и отображения.

Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «defer, анонимные функции и замыкания» бесплатный?

Да — полный текст урока «defer, анонимные функции и замыкания» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «defer, анонимные функции и замыкания»?

Отложенные вызовы и значения функций Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «defer, анонимные функции и замыкания»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы функций и сигнатуры
  2. Несколько возвращаемых значений
  3. Функции с переменным числом аргументов
  4. defer, анонимные функции и замыкания
← Назад к Go Academy