1. defer和defer的执行顺序
1.1 代码示例
func f4() {
defer func() {
fmt.Println("444")
}()
defer func() {
fmt.Println("555")
}()
println("dddddd")
}
func main() {
f4()
}
输出:
dddddd
555
444
如图可知,defer之间的输出顺序遵循栈的逻辑----先进后出,首先执行主程序代码,然后执行defer逻辑,在前面的defer最后执行,以此类推。
2. defer和return的执行顺序
2.1 当return的参数是无命名变量时
ps 无命名变量:返回值列表只要返回类型没有变量名
eg:
func f() int {
i := 5
defer func() {
i++
}()
return i
}
func main() {
println(f())
}
输出:
5
分析:如图可知,当返回的是无名明变量时,i的值在defer中的改变将被忽略,因为return的是无名明变量,则return不是原子操作,则return执行逻辑如下
1)var s int // 声明一个有命名变量
2)s:=i
3) 执行defer语句
4) return s
因为i在defer中的改变不会影响s的值,所以返回5
2.2 当return的参数是有命名变量,且返回的是具体数字时
eg:
func f1() (result int) {
defer func() {
result++
}()
return 5
}
func main() {
println(f1())
}
输出:
6
分析:内部执行逻辑
1)result=5 // result为返回的有命名参数
2) defer 语句 result变为6
3)return result=6
2.3 当return的参数是有命名变量,且返回的是自定义的局部变量时
eg:
func f2() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
func main() {
println(f2())
}
输出:
5
分析:return执行逻辑如下:
1)r=t (t变为5) // r为返回的有命名参数
2) defer 语句 r变为10
3)return r=5
2.4 当return的参数是有命名变量,且返回的也是命名变量时,且defer是闭包时
eg:
func f3() (r int) {
defer func(r int) {
r = r + 5
}(r)
return r
}
func main() {
println(f3())
}
输出:
0
分析:return执行逻辑如下:
1)r=0 (r变为0) // r为返回的有命名参数
2) defer 语句执行:
defer func(r int) { // 重新定义的r 跟外部的r不是一个地址
r = r + 5
}(r) // 外部传递的r为值传递
上式等价于下式:
defer func(a int) {
a = a + 5
}(r)
由于r在参数传递过程中是值传递,所以其本身不会随闭包值得改变而改变(地址不同),则外边r为0
3)return r=0
2.5 当return的参数是有命名变量,且返回的也是命名变量时,且返回参数跟defer中是一个参数时。
eg:
package main
import "fmt"
func test1(x int) int {
defer func() { x = 9 }()
x = 10
return x
}
func main() {
fmt.Println("Hello, World!",test1(100))
}
分析:???,不应该是9吗,原因待查,希望知道大神指导下。
输出:10
3. defer源码
待分析