• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

go 语言之defer

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

defer

对于go语言里面的defer关键字来说,是表示延迟调用,通常用于关闭一些资源,比如打开的文件资源,socket连接,同时也配合recover函数来处理panic的异常。
1、单个defer例子:

func test1(){
	fmt.Println("start")
	defer fmt.Println("defer")
	fmt.Println("end")
}

func main() {
	test1()
}

上述输出结果是:

start
end
defer

2、多个defer例子

func test1(){
	fmt.Println("start")
	defer fmt.Println("defer1")
	defer fmt.Println("defer2")
	fmt.Println("end")
}

func main() {
	test1()
}

输出结果

start
end
defer2
defer1

说明:对于多个defer来说,执行的顺序与定义的顺序是相反的。
比如:对于上述的代码,在执行到第一个defer的时候,go编译器会把当前的derfer放到一个栈里面,然后执行下一行代码,发现下一行代码也是defer,那么也会放到同一个栈(因为属于同一个函数作用域),当函数执行完成以后,准备返回时,发现还有defer语句没有执行,那么就会从栈里面把defer语句拿出来执行。由于栈是先进后出,也就说明了defer是先定义后执行了。

3、defer执行的时机在说明
一般来说,对于函数没有返回值的情况下,defer并不影响最终的结果,当函数有返回值时,来看看下面的一个例子:

func test2() int{
	x := 1
	defer func ()  {
		x++
	}()

	return x
}

func main() {
	fmt.Println(test2())
}

执行结果:

1

可以发现,函数最终返回的结果是1,而不是2.
说明:
go语言当中 return并不是原子性的,对于 return x来说,首先执行的是对x赋值,然后在执行return。二defer关键字的执行时机就是在x赋值之后,return之前。
那么为什么最终返回的是1而不是2呢?
个人理解如下:
由于函数的返回值是没有命名的返回值类型,所以当执行到return x以后,保存的是x这个变量的副本,但是由于x是值类型,所以这个副本里面存储的是真真实实的int类型,也就是1,所以后续在defer里面对x++,改变的是x的值,对于return后面的副本来说是不会修改的。其实这有点类似函数的形参与实参的区别。

那么再来看一个下面的例子:

func test2() []int{
	x := []int{1,2,3}
	defer func ()  {
		x[0] = 10
	}()

	return x
}

func main() {
	fmt.Println(test2())
}

返回结果:

[10 2 3]

其实这就跟上述说的一致,return x语句的x保存的是一个副本,但是由于x是一个引用类型,所以在defer里面进行对x修改以后,最终的x值也就发生了变化。

在来看一个命名返回值参数类型的函数

func test3() (x int){
	defer func ()  {
		x = 20
	}()

	x = 10
	return
}

func main() {
	fmt.Println(test3())
}

函数返回值:

20

为什么是20呢?
这是因为这是一个命名返回值的函数,在go语言当中,命名返回值当中的x就已经是一个实实在在的变量了,所以当在函数当中进行修改的时候,最终都是修改的这个x值。
同理,看一下下面这个函数的返回值是什么:

func test3() (x int){
	defer func ()  {
		x = 20
	}()

	x = 10
	return 5
}

func main() {
	fmt.Println(test3())
}

这里依然返回20,因为命名返回值来说,返回的就是x的值。跟5就没什么关系了。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap