Оператор defer
Оператор defer откладывает выполнение функции до тех пор, пока не завершится функция, в которой он был вызван. Это удобно для выполнения операций очистки, закрытия файлов или освобождения ресурсов. Отложенная функция выполняется в любом случае, даже если возникла паника.
Синтаксис
defer functionCall()
После ключевого слова defer указывается вызов функции или метода, который будет выполнен после завершения окружающей функции.
Пример использования defer
Давайте рассмотрим простой пример использования defer для выполнения действия перед завершением функции:
package main
import "fmt"
func main() {
defer fmt.Println("World")
fmt.Println("Hello")
}
Результат выполнения кода:
Hello
World
Несмотря на то что вызов defer находится перед выводом "Hello", отложенная функция выполняется после завершения функции main, поэтому сначала выводится "Hello", а затем "World".
Пример с закрытием файла
Часто defer используется для гарантированного закрытия ресурсов, таких как файлы или сетевые соединения:
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Create("example.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
defer file.Close()
file.WriteString("Hello, World!")
fmt.Println("File written successfully")
}
Результат выполнения кода:
"File written successfully"
Файл будет закрыт автоматически при выходе из функции main, даже если произойдет ошибка или паника.
Порядок выполнения отложенных функций
Если в функции указано несколько операторов defer, они выполняются в порядке, обратном их объявлению (LIFO - Last In First Out):
package main
import "fmt"
func main() {
defer fmt.Println("Third")
defer fmt.Println("Second")
defer fmt.Println("First")
fmt.Println("Main function")
}
Результат выполнения кода:
Main function
First
Second
Third
Отложенные функции выполняются в обратном порядке: последний объявленный defer выполняется первым.
Пример с паникой
Отложенная функция выполняется даже при возникновении паники, что позволяет безопасно освободить ресурсы:
package main
import "fmt"
func main() {
defer fmt.Println("Deferred function executed")
fmt.Println("Before panic")
panic("Something went wrong")
fmt.Println("After panic")
}
Результат выполнения кода:
Before panic
Deferred function executed
panic: Something went wrong
...
Несмотря на панику, отложенная функция выполняется перед завершением программы.
Пример с изменяемыми аргументами
Аргументы отложенной функции вычисляются в момент вызова defer, а не в момент выполнения:
package main
import "fmt"
func main() {
i := 0
defer fmt.Println("Deferred value:", i)
i = 42
fmt.Println("Current value:", i)
}
Результат выполнения кода:
Current value: 42
Deferred value: 0
Переменная i была изменена после объявления defer, но отложенная функция запомнила ее значение на момент вызова defer.