Go基础知识----defer源码和多个defer执行顺序

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源码

待分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值