defer
Отложенный вызов
defer откладывает выполнение функции до возврата из текущей функции:
func readFile(name string) {
f, _ := os.Open(name)
defer f.Close() // выполнится при выходе из readFile
// работа с файлом
}
Ресурс открыт и сразу «подстрахован» — независимо от того, сколько путей выхода из функции.
LIFO
Несколько defer выполняются в порядке LIFO — последний зарегистрированный вызывается первым:
func main() {
defer fmt.Println("третий")
defer fmt.Println("второй")
defer fmt.Println("первый")
}
// первый
// второй
// третий
Вычисление аргументов
Аргументы отложенной функции вычисляются в момент регистрации defer, а не при вызове:
x := 5
defer fmt.Println(x) // напечатает 5, даже если x изменится
x = 10
defer — стандартный паттерн для освобождения ресурсов: закрыть файл, разблокировать мьютекс, завершить транзакцию. Надёжнее, чем вручную следить за всеми путями возврата.
Упражнения
| № | Задание | Сложность |
|---|---|---|
| 1 | Упражнение 1 | easy |
| 2 | Упражнение 2 | easy |
| 3 | Упражнение 3 | medium |
| 4 | Упражнение 4 | medium |