被這個坑搞得有點慘。查了些資料,特此記錄下。
在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操作不到。當然,指針變量。。。為所欲為!
