См. Defer_statements :
Каждый раз, когда выполняется оператор "defer", значение функции и параметры для вызова оцениваются как обычно и сохраняются заново, но фактическая функция не вызывается. Вместо этого отложенные функции вызываются непосредственно перед возвратом окружающей функции в обратном порядке. То есть, если окружающая функция возвращается через явный оператор возврата, отложенные функции выполняются после того, как этот оператор возврата установит какие-либо параметры результата, но до того, как функция вернется к своему вызывающему. Если значение отложенной функции имеет значение nil, выполнение вызывает панику при вызове функции, а не при выполнении оператора defer.
Также см. Пример для ключевого слова go
Чтобы понять порядок оценки, давайте попробуем это:
defer having()(fun("with Go."))
Давайте запустим this и прочитаем комментарии к коду для порядка оценки:
package main
import "fmt"
func main() {
defer having()(fun("with Go."))
fmt.Print("some ") // evaluation order: 3
}
func having() func(string) {
fmt.Print("Go ") // evaluation order: 1
return funWithGo
}
func fun(msg string) string {
fmt.Print("have ") // evaluation order: 2
return msg
}
func funWithGo(msg string) {
fmt.Println("fun", msg) // evaluation order: 4
}
Вывод:
Go have some fun with Go.
Этот еще красивее, с тем же результатом, просто замените все функции на анонимные функции:
package main
import "fmt"
func main() {
defer func() func(string) {
fmt.Print("Go ") // evaluation order: 1
return func(msg string) {
fmt.Println("fun", msg) // evaluation order: 4
}
}()(func(msg string) string {
fmt.Print("have ") // evaluation order: 2
return msg
}("with Go."))
fmt.Print("some ") // evaluation order: 3
}
Надеюсь, это поможет вам понять, как работает defer
:
A рабочая версия вашего кода с достаточным количеством документации внутри (Примечание: defer
параметры оцениваются первыми на местеи вызов fmt.Println
будет отложен до возврата функции в обратном порядке):
package main
import "fmt"
func printTicket(age int) float64 {
fmt.Println("...order is 2...")
switch {
case age <= 13:
return 9.99
case age > 13 && age < 65:
return 19.99
default:
return 12.99
}
}
func main() {
age := 999
defer fmt.Println("...order is 4...Your age is:", getAge(&age))
defer fmt.Println("...order is 3...Your ticket price is:", printTicket(age))
}
func getAge(age *int) int {
fmt.Println("...order is 1...")
fmt.Print("Enter age=")
fmt.Scanln(age)
return *age
}
Выход:
...order is 1...
Enter age=999
...order is 2...
...order is 3...Your ticket price is: 12.99
...order is 4...Your age is: 999