代码如下:
package main
import "fmt"
//defer
//defer语句多用于函数结束之前释放资源(文件句柄、数据库连接、socket连接)
func deferDemo() {
fmt.Println("start")
defer fmt.Println("嘟嘟") //defer把它后面的语句延迟到函数即将返回时候在执行
defer fmt.Println("一一") //一个函数中可以有多个defer语句
defer fmt.Println("8号") //多个defer语句按照先进后出(后进先出)的顺序延迟执行
fmt.Println("end")
}
func main() {
deferDemo()
}
关于defer的面试题
面试题一:
加深对于defer的理解:
package main
import "fmt"
//go语言中函数的return不是原子操作,在底层是分为两步来执行的
//1:返回值赋值
//defer
//2:真正的RET返回
//函数中如果存在defer,那么defer执行的时机是在第一步和第二步之间
func f1() int {
x := 5 //修改的是x,不是返回值
defer func() {
x++
}()
return x
}
func f2() (x int) {
defer func() {
x++
}()
return 5 //返回值=x
}
func f3() (y int) {
x := 5
defer func() {
x++
}()
return x //返回值=y=x=5
}
func f4() (x int) {
defer func(x int) {
x++ //改变的是函数中的副本
}(x)
return 5 //返回值=x=5
}
func main() {
fmt.Println(f1())
fmt.Println(f2())
fmt.Println(f3())
fmt.Println(f4())
}
面试题二
下面的代码输出结果是什么?
package main
import "fmt"
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}
分析:
defer规则:先进后出或者后进先出;但是需要先把参数传进去。
先观察main()函数,里面有两个defer所以会先把参数传进去下面是步骤:
calc()函数中第一个参数是index,第二个是a,第三个是b;返回值ret=a+b,也就是main()函数里calc参数为cala(a,b,ret)
输出四个值:index, a, b, ret
1、先走到defer calc("AA", x, calc("A", x, y))
此处是第一个defer要最后执行,但是需要先把参数传入,此时calc("AA",1,calc('A'),x,y);此时又调用了calc函数,这个calc()作为参数传入的,需要先执行:calc('A'),x,y输出的是①:A 1 2 3
这时第一个defer里变为calc("AA",1,3),调用calc()函数输出④:AA 1 3 4
2、走到第二个defer calc("BB", x, calc("B", x, y))
此时x=10,y=2;此时calc("BB", 10, calc("B", 10, 2)),先执行参数里的calc()函数calc("B", 10, 2)输出的是②B 10 2 12;然后此时第二个defer的calc参数变为calc("BB",10,12),输出为③
B 10 12 22;
所以最终执行顺序为①②③④也是就是:
A 1 2 3
B 10 2 12
B 10 12 22
AA 1 3 4