首頁 > 後端開發 > Golang > 為什麼在 Go 中延遲關閉擷取會導致意外行為?

為什麼在 Go 中延遲關閉擷取會導致意外行為?

Linda Hamilton
發布: 2024-11-10 19:35:02
原創
513 人瀏覽過

Why Does Deferring Closure Capture in Go Lead to Unexpected Behavior?

Go 中延遲閉包擷取

Go 的 defer 語句可用於在周圍函數傳回後執行函數。然而,當與閉包一起使用時,了解參數捕獲的工作原理非常重要。

問題

考慮以下程式碼:

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()
    } // part 2

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)
    } // part 3
}
登入後複製

程式碼的輸出是:

0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
登入後複製

分析

  • 第1 部分:
  • 依預期列印循環計數器i。
  • 第 2 部分:
  • 捕捉閉包中的變數 i。但是,當閉包執行時, i 具有循環最後一次迭代的值,即 4。因此,它印出“44444”。
  • 第 3 部分:
  • 不捕獲任何外部變數。執行 defer 語句時會評估閉包,因此每個 defer 呼叫都有不同的 n 值,結果為「43210」。

主要區別

第 2 部分和第 3 部分之間的關鍵區別在於閉包是否捕獲外部變數。在第 2 部分中,閉包捕獲 i,它是對外部變數的引用。在第 3 部分中,閉包沒有任何外部引用,因此每個呼叫都有不同的 n 值。

其他注意事項

  • 延遲呼叫是在周圍函數返回之前按後進先出 (LIFO) 順序執行。
  • defer 語句時計算的表達式執行,而不是函數本身。

以上是為什麼在 Go 中延遲關閉擷取會導致意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板