golang中defer和return的顺序

6 阅读1分钟

被这个坑搞得有点惨。查了些资料,特此记录下。

在golang中,如果在defer 中操作返回数,往往会比较头晕。

例1:

 func f1() (i int) {
  i = 1
  defer func(){
     i++ 
  }
  return i
}

要点:
return是分为两步执行的,第一步赋值给返回值,第二步真正的返回到函数外部。而defer是在第一步之后执行。
所以,例1中,“return i”其实是把 i赋值给返回值i(当然,这里return的值就是i,所以其实没有赋值),此时i=1,然后再执行 defer,i=2,返回的i最终值是2。

例2:

func f2() int {  
    i := 1  
    defer func(){i++}()
    
    return i
}

例2这里,“return i”把i=1赋值给返回值,但是这里的返回值没有显示声明,会生成一个临时变量,假设叫‘tmp’,即tmp=1。然后,执行defer的时候,i=2。但是这个和'tmp'没关系。所以最终返回的是1。

例3:

func f2() *int {  
    i := 1  
    defer func(){i++}()
    
    return &i
}

例3这里,“return &i”把i的地址赋值给返回值,同样是临时变量‘tmp *int’。即,真正返回的是i的地址*tmp。然后,执行defer的时候,对tmp指针没操作,但是tmp指向的那个值(即i),修改成了2。所以,如果对返回的指针取值,结果是2。和传址参数一样理解。

 

综上,如果是显式命名的返回值,则defer中可以对其操作。如果是非显式命名的返回值,则返回时会新定义一个返回变量,defer操作不到。当然,指针变量。。。为所欲为!

【迁移】www.cnblogs.com/zxq89/p/135… posted @ 2020-08-31 21:06