一、定义
defer
是一种关键字,用于在函数返回前执行一些操作。
defer
语句可以将一个函数调用推迟到当前函数返回之前执行。
defer
语句可以在函数内部的任何地方定义,并且可以定义多个defer
语句。当函数返回时,defer
语句会按照后进先出(LIFO)的顺序执行,即最后定义的defer
语句最先执行。
二、代码示例
package main
import "fmt"
func main() {
// defer 的执行顺序与定义顺序相反,最先声明的最后执行
defer fmt.Println("我是1")
defer fmt.Println("我是2")
defer fmt.Println("我是3")
fmt.Println("我是4")
}
打印结果
我是4
我是3
我是2
我是1
defer
也可以修饰函数,意为可以将一个函数调用推迟到当前函数返回之前执行。
但是注意defer
语句不是延迟执行语句。它并不会使函数内部的语句推迟执行,而只是将某个函数调用推迟到函数返回之前执行。
package main
import "fmt"
func main() {
a := 1
b := 2
defer func() {
fmt.Println("defer1 => a+b=", a+b)
}()
defer func(a, b int) {
fmt.Println("defer2 => a+b=", a+b)
}(a, b)
a = 2
fmt.Println("main")
}
打印:
main
defer2 => a+b= 3
defer1 => a+b= 4
在main中写了两个匿名函数,第一个是闭包获取变量
,第二个是函数传参
。
但是它俩的结果是不一样的,这也是印证了上面的 defer可以将一个函数调用推迟到当前函数返回之前执行
defer func() {
fmt.Println("defer1 => a+b=", a+b)
}()
该匿名函数为闭包获取参数
,是引用传递,所以对该函数来说,内部的a和b是main函数中a和b的地址引用。
defer func(a, b int) {
fmt.Println("defer2 => a+b=", a+b)
}(a, b)
由于a,b在之前已经赋值了1和2,因此当程序执行到此处时,该匿名函数已经完成了它的定义,它内部只认a=1,b=2,因此这种传参是值复制。
总结:defer 调用的函数,参数的值在 defer 定义时就确定了,看下代码
defer fmt.Println(a + b)
,在这时,参数的值已经确定了。
而 defer 函数内部所使用的变量的值需要在这个函数运行时才确定,看下代码
defer func() { fmt.Println(a + b) }()
,a 和 b 的值在函数运行时,才能确定。
三、打断施法
当程序使用**os.Exit()**时,程序会直接退出,而defer
和return
也不会被执行。
package main
import (
"fmt"
"os"
)
func main() {
defer fmt.Println("执行defer")
fmt.Println("main")
a := func() int {
os.Exit(0)
return 1
}()
fmt.Println("a:", a)
}
打印:
main