深入defer
defer
语句将函数标记为在当前函数的最后执行。
延迟调用就是在普通函数的前面加上defer
关键字。
defer someFunction()
包含defer
语句的函数一旦要返回时,被defer
标记的延迟函数就会被调用。延迟函数真正被调用的时机是,当包围函数:
执行返回语句
正常执行到最后
发生了恐慌
例子:
func logExit(name string) {
fmt.Printf("Function %s returned\n", name)
}
func main() {
fmt.Println("First main statement")
defer logExit("main") // defer语句的位置无关紧要
fmt.Println("Last main statement")
}
如果一个函数中有多个延迟语句,它们将形成一个栈。最后一个defer
是在闭包函数返回之后第一个执行的,随后依次调用先前的defer
(下方例子会因panic而返回):
func logNum(i int) {
fmt.Printf("Num %d\n", i)
}
func main() {
defer logNum(1)
fmt.Println("First main statement")
defer logNum(2)
defer logNum(3)
panic("panic occurred")
fmt.Println("Last main statement") // 不会被打印
// 下面不会执行,因为执行流程永远不会到达此行
defer logNum(4)
}
延迟函数的参数的值,是它们在被解析求值时的值(而不是最后返回时的值)。
package main
import (
"fmt"
)
func logNum(i int) {
fmt.Printf("Num %d\n", i)
}
func main() {
i := 1
defer logNum(i) // deferred function call: logNum(1)
fmt.Println("First main statement")
i++ //i=2
defer logNum(i) // deferred function call: logNum(2)
i++ // i = 3
defer logNum(i * i) // deferred function call: logNum(9)
}
---------Output---------
First main statement
Num 9
Num 2
Num 1
如果一个函数有具名返回值,在该函数中的匿名defer
调用可以在其返回之前修改函数的返回值。
func plusOne(i int) (result int) {
// 匿名函数之后必须加 () 进行调用
defer func() { result++ }()
// i 作为结果被返回, 它会被上面的延迟调用函数修改
return i
}
func main() {
fmt.Println(plusOne(1)) // 2
}
最后更新于
这有帮助吗?