亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

defer 和命名返回值是如何工作的?

defer 和命名返回值是如何工作的?

Go
慕容708150 2022-01-10 16:38:56
我剛開始學習 Go,我對The Go Blog - Defer, Panic, and Recover 中關于使用 defer 更改命名返回值的一個示例感到困惑。該示例說:延遲函數可以讀取并分配給返回函數的命名返回值。在此示例中,延遲函數在周圍函數返回后遞增返回值 i。因此,此函數返回 2:func c() (i int) {    defer func() { i++ }()    return 1}但正如我從A Tour of Go中學到 的 - 命名返回值沒有參數的 return 語句返回指定的返回值。這被稱為“裸”回報。我在下面的代碼和函數中進行了測試,b它返回 1 因為它不是上面提到的“ A return statement without arguments ”的情況。func a() (i int) { // return 2    i = 2    return}func b() (i int) {  // return 1     i = 2    return 1}所以我的問題是在第一個例子中,周圍的函數C有一個名為返回值我,但功能c用途return 1,其在第二個例子中,我們可以看到它應該有回報1無論什么價值i的。但是為什么在i延遲函數更改后,c函數返回值i而不是值 1?當我輸入我的問題時,我可能已經猜到了答案。是不是因為:return 1 等于:i = 1return 在具有命名返回值變量的函數中i?請幫我確認一下,謝謝!
查看完整描述

3 回答

?
守著一只汪

TA貢獻1872條經驗 獲得超4個贊

defer 語句將函數調用推送到列表中。保存的調用列表在周圍函數返回后執行。-- Go 博客:延遲、恐慌和恢復


理解上述語句的另一種方式:


defer 語句將函數調用壓入堆棧。彈出的已保存調用堆棧(LIFO)和延遲函數在周圍函數返回之前立即調用。


 func c() (i int) {

    defer func() { i++ }()

    return 1

}

返回 1 后,func() { i++ }()執行延遲。因此,按照執行順序:


i = 1(返回 1)

i++(延遲函數從堆棧中彈出并執行)

i == 2(命名變量 i 的最終結果)

為了理解起見:


 func c() (i int) {

    defer func() { fmt.Println("third") }()

    defer func() { fmt.Println("second") }()

    defer func() { fmt.Println("first") }()


    return 1

}

執行順序:

  1. i = 1(返回 1)

  2. “第一的”

  3. “第二”

  4. “第三”


查看完整回答
反對 回復 2022-01-10
?
Smart貓小萌

TA貢獻1911條經驗 獲得超7個贊

根據 Go 規范:

返回語句 指定結果的“返回”語句在執行任何延遲函數之前設置結果參數。

Defer 語句 “......在周圍函數返回之前立即調用延遲函數......”

所以是的,正如你所假設的,命名的返回變量被賦值,然后延遲語句增加它。

我要補充一點,命名返回參數可能會導致細微的錯誤,除非沒有其他選擇,否則通常應該避免。


查看完整回答
反對 回復 2022-01-10
?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

我認為混淆是關于功能中的功能,如果你這樣分類:


  func main() {

      fmt.Println(c()) //the result is 5

  }


  // the c function returned value is named j

  func c() (j int)  {

      defer changei(&j)

      return 6

  }

  func changei(j *int) {

      //now j is 6 because it was assigned by return statement 

      // and if i change guess what?! i changed the returned value

      *j--;

  }

但是如果返回值不是這樣命名的:


  func main() {

      fmt.Println(c()) //the result will become 6

  }


  // the c function returned value is not named at this time

  func c() int  {

      j := 1

      defer changei(&j)

      return 6

  }

  func changei(j *int) {

      //now j = 1

      // and if i change guess what?! it will not effects the returned value

      *j--;

  }

我希望這能消除混亂,這就是我快樂 Go 編碼的方式


查看完整回答
反對 回復 2022-01-10
  • 3 回答
  • 0 關注
  • 239 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號