关于defer的的官方文档:https://golang.org/ref/spec#Defer_statements (需翻墙)
A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.
defer语句会在这几种情况下执行defer后面的函数
- 函数执行return返回语句
- 到达的函数体的末尾
- goroutine发生panic异常
DeferStmt = "defer" Expression .
The expression must be a function or method call; it cannot be parenthesized. Calls of built-in functions are restricted as for expression statements.
表达式必须是函数或者方法的调用。不能用圆括号括起来。把内置函数作为表达式调用会受到限制
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferred function value evaluates to nil
, execution panics when the function is invoked, not when the "defer" statement is executed.
每次执行defer语句时,调用函数的值和参数会像往常一样求值并重新保存,但不会调用实际的函数。相反,defer后面的函数会在它所在的函数(周围函数)返回之前立即调用,顺序与延迟的顺序相反。也就是说,如果周围的函数通过显式return语句返回,则在return语句设置任何结果参数之后,但在函数返回其调用方之前,将执行延迟函数。如果deferred函数值的计算结果为nil,则在调用函数时执行会产生panics,而不是在执行“defer”语句时。
For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned. If the deferred function has any return values, they are discarded when the function completes. (See also the section on handling panics.)
例如,如果延迟函数是一个函数字面量,并且周围函数的结果参数在函数字面量范围内,则延迟函数可以在返回结果参数之前访问和修改结果参数。如果延迟函数有任何返回值,则在函数完成时将丢弃它们。(另请参阅处理panics一节。)
例1:
package main
import "fmt"
func main() {
fmt.Println("函数返回值:",fun1())
}
func fun1() int {
i := 0
defer func() {
fmt.Println("第1次", i)
i++
}()
defer func() {
fmt.Println("第2次", i)
i++
}()
defer func() {
fmt.Println("第3次", i)
i++
}()
return i
}
结果:
第3次 0
第2次 1
第1次 2
函数返回值: 0
例2:
package main
import "fmt"
func main() {
fun1() //结果:0
fun2() //结果:3 2 1 0
fmt.Println()
fmt.Println(fun3()) //结果:42
}
func fun1() {
i := 0
defer fmt.Println(i)
i++ //这里的自增不会影响defer打印i变量
return
}
// prints 3 2 1 0 before surrounding function returns
// 顺序与defer后面函数加载的顺序相反
func fun2() {
for i := 0; i <= 3; i++ {
defer fmt.Print(i, "\t")
}
}
// f returns 42
func fun3() (result int) {
defer func() {
// result is accessed after it was set to 6 by the return statement
result *= 7
}()
return 6
}
例2
package main
import "fmt"
func main() {
fmt.Println(f1()) //1
fmt.Println(f2()) //5
fmt.Println(f3()) //10
fmt.Println(f4()) //1
}
func f1() (result int) {
defer func() {
//这个是函数返回结果result,这里改变了,函数返回值也会改变
result++
}()
return 0
}
func f2() (r int) {
t := 5
defer func() {
//函数返回列表的变量是r,这里改变不会影响函数返回值
t = t + 5
}()
return t
}
func f3() (r int) {
r = 5
defer func() {
//函数返回变量r,这里改变会影响返回值
r = r + 5
}()
return r
}
func f4() (r int) {
defer func(r int) {
//注意go语言参数的范围
//这里的r是defer函数传进来的r,不是函数f4返回值列表的r,不会影响f4函数的返回值
r = r + 5
}(r)
return 1
}