golang之defer
来源:互联网 发布:java选课源代码 编辑:程序博客网 时间:2024/06/10 23:26
点击上方蓝色字体关注我们
golang 中的延迟调用函数
延迟调用函数(Deferred Function Calls)的调用方式如下:
defer func_name(param-list)
1 执行的时机
func f1() (ret int) {
defer func() {
ret++
}()
return 0
}
func f2() (ret int) {
tmp := 1
defer func() {
tmp = tmp + 10
}()
return tmp
}
func f3() (ret int) {
defer func(ret int) {
ret = ret + 10
}(ret)
return 1
}
先不要运行程序,心里记下自己认为分别运行这三个函数的结果,然后我们慢慢分析。
这里先说结论:
网上有篇博文讲的defer的实现方式就是在defer出现的地方插入指令:
CALL runtime.deferproc
然后在函数返回之前的地方插入指令:
CALL runtime.deferreturn
同时由于 return ret这一句并不是原子操作,它是分为两步来执行的:
(1)先在栈中写一个值,这个值被当作返回值;
(2)然后调用空的return语句。
那么有了defer之后,defer的执行是被插入在return之前赋值指令之后的。
有了这个结论,我们来分析前面的代码的结果:
f1():先给返回的值ret=0赋值,然后执行defer,把ret++,这样最后返回出来的结果就是 1 ;
f2():return之前 tmp的值是1,执行ret = 1,然后执行defer,把tmp+=10,此时在返回,不影响返回结果,最终结果还是1;
f3():return之前,先执行ret=1的赋值操作,然后,将ret值传递给匿名函数,执行的结果不影响之前的值,所以ret函数最终的返回值是1。
2 执行的顺序
func f4() {
defer func() {
fmt.Println("1-1")
defer func() {
fmt.Println("1-1-1")
}()
}()
defer func() {
fmt.Println("2-2")
defer func() {
fmt.Println("2-2-2")
}()
}()
}
猜猜看,调用f4之后出现的打印是什么:
结论是
可以看出它是基于先进后出的方式存储defer函数的,也就是逆序执行的。
在goroutine的控制结构中,有一张表记录defer,调用runtime.deferproc时会将需要defer的表达式写入表中,而在调用runtime.deferreturn的时候,则会依次从defer表中取出并执行。
3 使用defer值得注意的地方
1 经常在加锁的地方紧接着使用 defer 去解锁,这样写是非常方便,不用在加锁之后,每个return的地方都要去解锁,但是别忘了加锁之后要是有阻塞的操作,导致函数一直没有办法返回,那么就出现了问题。
func f5() {
lc.Lock()
defer lc.Unlock()
for { // 长期执行某个操作
if 0 { // 达到某种条件之后退出
break
}
}
return
}
如上f5(),如果lc这把锁有其他的地方在用,那么就导致了死锁的问题。
扫描二维码关注我们
查看原文:http://www.zoues.com/2016/10/20/golang%e4%b9%8bdefer/
- golang之defer
- golang之defer
- golang之defer
- golang defer
- golang之defer,panic,recover用法
- golang中defer精析
- golang defer 功能说明
- golang的defer详解
- golang defer讲解
- Golang从入门到精通(二十二):Golang错误处理之defer
- golang中的defer panic recover
- golang中defer的执行
- golang中的defer panic使用方法
- Golang---Defer, Panic, and Recover
- go语言 golang defer 关注点
- Golang中的defer, panic, recover
- Golang 中 defer 小坑
- Golang有多个defer的情况
- Golang语言--select
- golang的错误处理
- Golang语言--测试技术
- golang的哪些坑爷事: package实践--转
- Golang和HTTPS在网站前端接入里的作用
- golang之defer
- 设计模式之观察者模式
- 驱动问题总结
- Golang基本数据类型,常量,标识符
- Golang语言和node.js的对比
- golang的内存模型与new()与make()
- Linux Ubuntu14.04在线安装配置Nginx
- Golang中一个不错的处理 JSON 的库 go-dproxy
- Golang 在 Baidu-FrontEnd 的应用之路