defer的使用

defer的使用

1、defer事什么?

defer是Go语言中代码延迟执行的语句,go语言代码段中的的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。(该特性联想进栈出栈,先进后出)

eg:

func main() {
	fmt.Println("start")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("end")
}

执行结果:

/*
start
end
3
2
1
*/

2、defer的执行机制

在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示:

在这里插入图片描述

3、练习题

package main

/*
defer 延迟执行,时机在第一步和第二步之间
return 不是原子操作,
第一步:返回值赋值
// defer
第二步:真正的RET指令返回

*/

func f1() int {
   x := 5
   defer func() {
      x++ //该步骤修改的是变量x,不是返回值,该函数的关键点在于,返回值<未被命名>,函数的runtime应该为:
      // 1,变量x被赋值5,2、返回值被赋值5 3、defer延迟执行修改变量x为6,4、最后执行return命令,返回了被赋值5的返回值
      //
   }()
   return x // 5
}
func f11() (x int) {
   defer func() { x++ }() // runtime:1、函数的返回值命名为x,初始值为0 ,return的非原子操作导致return语句的第一步使返回值x被赋值为5;
   //2、执行defer操作,使变量x(即在内存地址上跟返回值为同一个)经过++运算变为6;3、执行真正的return操作返回返回值x,即为6
   return 5 //6
}
func f2() (x int) {
   a := 1
   defer func() { //函数的runtime为:函数的返回值命名为x,初始值为0;变量a被赋值1;
      x++ // return语句的实际执行步骤:
      // 1、命名为x的返回值重新被赋值 x=a=1,
   }() // 2、执行defer语句,x++, x = 1+1 = 2
   // 3、执行真正的return指令,返回x为2
   return a // 2
}

func f3() (y int) {
   x := 5
   defer func() {
      x++
   }()
   return x //5 函数的runtime:函数的返回值命名为y,初始值为0;函数体中变量x被赋值5;
   // return语句的实际执行步骤:
   // 1、y = x = 5
   // 2、defer执行:x=5+1=6
   // 3、return真正执行,返回值y=5
}

func f4() (x int) {
   defer func(x int) {
      x++
   }(x)
   return 5 //函数的runtime:函数的返回值命名为x,初始值为0;
   // return语句的实际执行步骤:
   // 1、返回值被赋值x = 5
   // 2、defer执行:x作为函数参数传入匿名函数,执行 x=5+1=6,但是 "函数传参修改的是副本"
   // 3、return真正执行,返回值x=5
}
func f5() int {
   x := 0
   defer func(x int) {
      x++
   }(x)
   return 5 // 5
}
func f6() (x int) {
   defer func(x *int) {
      *x++
   }(&x)
   return 5 // 6//函数的runtime:函数的返回值命名为x,初始值为0;
   // return语句的实际执行步骤:
   // 1、返回值被赋值x = 5
   // 2、defer执行:x的指针作为函数参数传入匿名函数,执行 x=5+1=6,
   // 3、return真正执行,返回值x=6
}

//func calc(index string, a, b int) int {
// ret := a + b
// fmt.Println(index, a, b, ret)
// return ret
//}

func f7() (x int) {
   defer func(x int) int {
      x++ // 传递的是x的副本,不会对原值有影响
      return x
   }(x)
   return 5
}
func f8(x int) int {
   //var x  int
   return func(x int) int {
      x++
      return x // 1
   }(x)
   //return
}


参考:https://www.liwenzhou.com/posts/Go/09_function/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值