defer的一些要注意的点和defer面试题
defer使用场景
defer在Go语言中是一个十分常用的关键字,它的作用是:将其后面跟随的语句进行延迟处理
简单来说,就是程序先去干别的事情。最后再来做defer后面跟的东西
于是我们很容易就想到,defer可以用很多使用的场景
比如:
文件的关闭,资源的清理,解锁及记录时间,以及recover的使用
defer的一些特性
-
类似于栈的特性,所有的defer 语句都会像栈一样先进后出
-
执行时机:Go语言中的return语句并不是一个原子操作,它分为给返回值赋值和RET指令两步,而defer语句执行的时机其实就在返回值赋值操作之后,RET指令执行之前,如下图
两道defer面试题
func f1() int { //返回值没有取名
x := 5
defer func() {
x++
}()
return x //1.返回值赋值 2.defer 3.执行RET返回 //开辟了一份空间 return语句先将5赋值给x defer修改了x的值 但是RET命令执行的对象还是那个‘5’
}
func f2() (x int) { //返回值有名字
defer func() {
x++
}()
return 5 //修改的是x的值
}
func f3() (y int) {
x := 5
defer func() {
x++
}()
return x //y = x = 5 defer修改的是 x 真正返回的y还是5
}
func f4() (x int) {
defer func(x int) {
x++ //改的是函数值的副本 //如果这里是 defer func(x *int) { x ++ }(x)
}(x) //那么结果就会变成6
return 5
}
func main() {
fmt.Println(f1()) //5
fmt.Println(f2()) //6
fmt.Println(f3()) //5
fmt.Println(f4()) //5
}
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
//1.调用calc中的calc("A",x,y) 输出:"A",1,2,3 因为函数调用时会确定每个参数的值
//2.defer calc("AA",x,3)
//3.调用第二个calc中的calc("B",x,y) 此时x y是20 输出:"B",10,2,12
//4.defer calc("BB",x,12)
//5.先进后出 调用第二个calc 输出:"BB",10,12,22
//6.调用第二个calc 输出:"AA" 1,3,4
}