go defer注意点,很容易出错的!!!
1:defer是在return之前执行的 函数返回的过程是这样的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中
返回值 = xxx 调用defer函数 空的return
func f() (result int) { result = 0 //return语句不是一条原子调用,return xxx其实是赋值+ret指令 func() { //defer被插入到return之前执行,也就是赋返回值和ret指令之间 result++ }() return }
func f() (r int) { t := 5 r = t //赋值指令 func() { //defer被插入到赋值与返回之间执行,这个例子中返回值r没被修改过 t = t + 5 } return //空的return指令 }
2:有名返回值和匿名返回值的问题
匿名返回值是在 return 执行时被声明,有名返回值则是在函数声明的同时被声明,因此在 defer 语句中只能访问有名返回值,而不能直接访问匿名返回值
此方法返回的是2 而不是1 之前在这困扰了好久,就是没弄明白对匿名返回值的函数是无法修改该返回值的,匿名返回值相当于又重新赋值了一个新的变量
func det2() int {
result := 2
println(&result)
defer func(result *int) {
println("det2")
*result = 1
println(*result)
}(&result)#所以对result无论如何修改都无法改变返回值的内容
#可变形为
匿名变量 = result
return 匿名变量
}
相反的 defer修饰的有名返回值的函数可以修改最后的返回值内容
func b() (i int) {
defer func() {
i++
fmt.Println(
"b defer2:"
, i)
// 打印结果为 b defer2: 2
}()
defer func() {
i++
fmt.Println(
"b defer1:"
, i)
// 打印结果为 b defer1: 1
}()
return
i
// 或者直接 return 效果相同
}
最终返回的结果i为2 ,若果将上述函数变为匿名返回值
func b() {
defer func() {
i++
fmt.Println(
"b defer2:"
, i)
// 打印结果为 b defer2: 2
}()
defer func() {
i++
fmt.Println(
"b defer1:"
, i)
// 打印结果为 b defer1: 1
}()
return
i
// 或者直接 return 效果相同
} 此时返回值为 0
3:defer 调用的函数参数的值在 defer 定义时就确定了, 而 defer 函数内部所使用的变量的值需要在这个函数运行时才确定func f1() (r int) {
r = 1
defer func() {
r++
fmt
.Println(
" r value = "
,r)
}()
r = 2
return
}
参考:https://www.jb51.net/article/127130.htm