Defer 用法說明:列印最終變數值
在 Go 中,defer 關鍵字允許我們安排一個函數在周圍函數返回。但是,如果延遲函數使用可能在周圍函數內更改的局部變量,則必須特別注意確保使用正確的值。
考慮以下函數:
func printNumbers() { var x int defer fmt.Println(x) for i := 0; i < 5; i++ { x++ } }
根據語言規範,當 defer 語句執行時,局部變數會被重新求值並儲存。然而,實際的函數直到稍後才會被呼叫。在這種情況下,執行 defer 語句時,x 的值為 0,因此在呼叫 deferred 函數時會列印 0。
要解決這個問題,我們可以使用以下幾種方法之一:
1。使用匿名函數:
defer func() { fmt.Println(x) }()
這使用捕獲 x 的當前值的匿名函數。當匿名函數被呼叫時,它將使用捕獲的值,即使 x 在周圍函數中發生了變化。
2.使用指標:
var x int defer Print(&x)
我們可以使用指向 x 的指標並延遲列印指向值的函數。這是可行的,因為執行 defer 語句時會計算指標值,但直到呼叫 deferred 函數才會計算指向的值。
3.使用自訂類型:
type MyInt int func (m *MyInt) String() string { return strconv.Itoa(int(*m)) } var x MyInt defer fmt.Println(&x)
在這裡,我們建立一個實作fmt.Stringer 介面的自訂類型MyInt,讓我們可以指定如何列印值。當 &x 被列印時,將呼叫 String 方法,並傳回指向值的字串表示形式。
4.包裝:
x := []int{0} defer fmt.Println(x)
將變數包裝在切片中允許我們延遲列印切片內容的函數。執行 defer 語句時會計算切片描述符,但直到呼叫延遲函數時才會計算底層數組。
請務必記住,延遲函數中使用的變數不應該是延遲函數本身,因為參數在延遲語句執行時被評估。
以上是Go中處理局部變數變化時如何正確使用Defer?的詳細內容。更多資訊請關注PHP中文網其他相關文章!