go语言的defer用法学习

defer是go中的一个关键字, 我们可以用该关键字实现函数退出时的资源关闭、回收等操作。 这里主要是学习下defer的执行顺序。

defer的语句按照添加的顺序逆序执行,即先进后出。 然后最后是函数返回。

但是还要注意一点的是defer的执行时机是:

1、外层函数设置返回值之后,并且在即将返回之前。

2、return xxx 操作并不是原子的。

这里三个代码实例和结果看下defer的执行情况

package main
import ("fmt")

func num1() int {
	var i int
	defer func() {
		i++
		fmt.Println("defer 2 : ", i)
	}()

	defer func() {
		i++
		fmt.Println("defer 1 : ", i)
	}()

	return i
}


func num2() (i int) {
	defer func() {
		i++
		fmt.Println("defer 2 : ", i)
	}()

	defer func() {
		i++
		fmt.Println("defer 1 : ", i)
	}()

	return i
}

func num3() *int {
	var i int
	defer func() {
		i++
		fmt.Println("defer 2 : ", i)
	}()

	defer func() {
		i++
		fmt.Println("defer 1 : ", i)
	}()

	return &i
}

func main() {
	fmt.Printf("for num 1 return is \n")
	fmt.Printf("return is %d \n", num1())
	fmt.Printf("for num 2 return is \n")
	fmt.Printf("return is %d \n", num2())
	fmt.Printf("for num 3 return is \n")
	fmt.Printf("return is %d \n", *num3())
}


上面代码的执行结果是:

for num 1 return is
defer 1 :  1
defer 2 :  2
return is 0
for num 2 return is
defer 1 :  1
defer 2 :  2
return is 2
for num 3 return is
defer 1 :  1
defer 2 :  2
return is 2

分析一下原因:
函数num1: 因为i变量是函数内不定义的。 return的时候已经把i的值返回了。 后面defer函数操作的是i已经跟返回的无关了。 所以return的是0 defer分别打印的是再增加之后的1和2.

函数num2:    因为i变量是函数调用时传入的。 return 返回的i和后面defer继续操作的仍然是同一个i, 所以defer 对i的改变仍然作用到了返回的那个i上面。

函数num3: 因为返回的是指针, 虽然var是在内部定义的,但是在返回的时候直接把这个返回出去了,所以defer后续的改变仍然也做用到了返回的那个i上面。

这点在C C++语言中是不可以的,因为其局部变量默认是栈空间的,而栈空间资源会再函数结束之后被回收。而在go中,个人理解是其自动管理的内存分配,其会判断变量恩声明周期而处理,所以返回指针也是安全的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值