golang defer && return

defer中去修改函数中的变量时,会出现个小坑:
修改函数中的变量会无效,如下面的函数a().

/*
func main() {
 k := a()
 fmt.Println("return:", k) // 打印结果为 return: 0
}

func a() int {
 var i int
 i = 0
 defer func() {
  i++
  fmt.Println("defer2:", i) // 打印结果为 defer: 2
 }()
 defer func() {
  i++
  fmt.Println("defer1:", i) // 打印结果为 defer: 1
 }()
 return i
}
*/

func main() {
 k := b()
 fmt.Println("return:", k) // 打印结果为 return: 2
}

func b() (i int) {
 defer func() {
  i++
  fmt.Println("defer2:", i) // 打印结果为 defer: 2
 }()
 defer func() {
  i++
  fmt.Println("defer1:", i) // 打印结果为 defer: 1
 }()
 i++
 return i // 或者直接 return 效果相同
}

/*
func main() {
 fmt.Println("c return:", *(c())) // 打印结果为 c return: 2
}

func c() *int {
 var i int
 defer func() {
  i++
  fmt.Println("c defer2:", i) // 打印结果为 c defer: 2
 }()
 defer func() {
  i++
  fmt.Println("c defer1:", i) // 打印结果为 c defer: 1
 }()
 return &i
}
*/

有个概念先解释下:
1.在有defer语句时,return语句并代表整个函数已退出
2.在go文档中有这么句:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usualand saved anew but the actual function is not invoked
defer语句出现的地方,值和参数就已经赋值并更新,只不过函数没有被调用
用栈来打个比方。defer函数在函数的栈底(相当有两个栈,defer栈和普通栈,defer栈存放defer函数,同时defer栈在return语句后),defer函数入栈时,会带上相应的环境.
对于 A来说,
return语句点i值确定了(0),defer不会也没办法改变其值,有点像函数的值传递,里面的值是无法改变外面的值的
对于B来说,
return语句点i确定为全局变量i,但是其值是不确定的,要等defer完了之后(既整个函数都执行完),才能确定.
对于C来说,
return语句点只确定了i的地址,值也是不确定的,要等defer完了之后(既整个函数都执行完),通过地址间接获取值

汇编厉害的话,在编译后的汇编中也可以看到,
a的话就是直接赋值,b的话就是全局变量,c会新建个object.
而且defer语句出现的地方,会直接插入一个call runtime.deferproc(SB),也就是前面那句,"defer语句出现的地方,值和参数就已经赋值并更新".
PS:我不懂汇编,自己通过对比汇编文件下理解出来的
go tool compile -S XXX.go 可以获得

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 能力模型 选择题 [primary] 下面属于关键字的是()A. funcB. defC. structD. cl...
    _张晓龙_阅读 24,979评论 14 224
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,840评论 0 9
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 10,210评论 1 19
  • 文/轻轻风 2016年即将过去了,总觉得什么没完成,心里空唠唠地。物质的来源,我的工作一直是我头疼的问题。 做销售...
    南城半世阅读 2,880评论 4 4
  • 画画一直是一个可望而不可及的梦想埋藏在心底的最深处,也许从描画妈妈绣花的底样时就开始有了吧。长大后一次次找借...
    秋泽917阅读 1,404评论 4 2