目錄
資源清理是最常見的使用場景
defer 的執行順序是後進先出(LIFO)
參數是在defer 寫下時就確定的
小技巧:避免defer 在循環中濫用
首頁 後端開發 Golang 解釋說明

解釋說明

Jul 14, 2025 am 02:57 AM

defer 的核心作用是推遲執行函數調用直到當前函數返回,常用於資源清理。具體包括:1. 確保文件、網絡連接、鎖等資源及時釋放;2. 執行順序為後進先出(LIFO),最後定義的defer 最先執行;3. 參數在defer 定義時即確定,非執行時求值,若需捕獲變量變化可用閉包或指針;4. 避免在循環中濫用defer,防止資源累積未及時釋放。

Go defer statement explained

Go 的defer語句看起來簡單,但用好了能提升代碼清晰度和健壯性。它的核心作用是推遲執行某個函數調用,直到當前函數返回時才執行。常用於資源釋放、解鎖、日誌記錄等場景。

Go defer statement explained

資源清理是最常見的使用場景

在處理文件、網絡連接、鎖等資源時,及時釋放非常重要。 defer可以確保這些操作在函數退出前一定被執行,避免遺漏。

比如打開一個文件進行讀取:

Go defer statement explained
 file, _ := os.Open("example.txt")
defer file.Close()

這樣無論函數怎麼退出(正常返回或中途出錯), file.Close()都會被調用。
如果你不加defer ,就得手動在每個return 前都寫一次file.Close() ,容易漏也顯得囉嗦。

常見資源清理場景包括:

Go defer statement explained
  • 文件關閉(如上面的例子)
  • 網絡連接關閉
  • 鎖的釋放(如mutex.Unlock()
  • 數據庫事務提交或回滾

defer 的執行順序是後進先出(LIFO)

當你在同一個函數里寫了多個defer ,它們的執行順序是反過來的:最後寫的先執行。

舉個例子:

 func main() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
}

輸出會是:

 3
2
1

這在嵌套資源管理中很有用。例如你打開了多個文件或者加了多層鎖,按相反順序釋放往往更安全。


參數是在defer 寫下時就確定的

這一點很多人容易忽略。 defer後面的函數參數是在定義時求值,而不是執行時。

看這個例子:

 func a() {
    i := 0
    defer fmt.Println(i)
    i  
}

運行這個函數,打印的是0 ,不是1 。因為i的值在defer定義時就已經確定了。

如果你想讓defer捕獲變量變化後的值,可以考慮傳指針或者用閉包:

 func b() {
    i := 0
    defer func() {
        fmt.Println(i)
    }()
    i  
}

這時打印的是1 。閉包會在實際執行時捕獲變量當前的值(注意這裡是引用,不是拷貝)。


小技巧:避免defer 在循環中濫用

雖然defer很方便,但在循環中使用要小心。因為它不會立即執行,累積太多可能造成內存佔用過高或資源未及時釋放。

比如:

 for _, filename := range filenames {
    file, _ := os.Open(filename)
    defer file.Close()
}

這段代碼的問題在於,所有文件都會在循環結束後才被關閉。如果文件很多,可能會超出系統限制。這種情況下,不如手動控制關閉。


基本上就這些。 defer是Go 中非常實用的特性,理解清楚它的工作機制,能幫你寫出更簡潔、更安全的代碼。

以上是解釋說明的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP教程
1596
276
以身作則http中間件記錄示例 以身作則http中間件記錄示例 Aug 03, 2025 am 11:35 AM

Go中的HTTP日誌中間件可記錄請求方法、路徑、客戶端IP和耗時,1.使用http.HandlerFunc包裝處理器,2.在調用next.ServeHTTP前後記錄開始時間和結束時間,3.通過r.RemoteAddr和X-Forwarded-For頭獲取真實客戶端IP,4.利用log.Printf輸出請求日誌,5.將中間件應用於ServeMux實現全局日誌記錄,完整示例代碼已驗證可運行,適用於中小型項目起步,擴展建議包括捕獲狀態碼、支持JSON日誌和請求ID追踪。

以身例子從stdin中讀取 以身例子從stdin中讀取 Jul 27, 2025 am 04:15 AM

使用fmt.Scanf可讀取格式化輸入,適合簡單結構化數據,但字符串遇空格截止;2.推薦使用bufio.Scanner逐行讀取,支持多行輸入、EOF檢測和管道輸入,並可處理掃描錯誤;3.使用io.ReadAll(os.Stdin)一次性讀取全部輸入,適用於處理大塊數據或文件流;4.實時按鍵響應需第三方庫如golang.org/x/term,常規場景使用bufio已足夠;實際建議:交互式簡單輸入用fmt.Scan,行輸入或管道用bufio.Scanner,大塊數據用io.ReadAll,且始終處理

Switch語句如何運行? Switch語句如何運行? Jul 30, 2025 am 05:11 AM

Go的switch語句默認不會貫穿執行,匹配到第一個條件後自動退出。 1.switch以關鍵字開始並可帶一個值或不帶值;2.case按順序從上到下匹配,僅運行第一個匹配項;3.可通過逗號列出多個條件來匹配同一case;4.不需要手動添加break,但可用fallthrough強制貫穿;5.default用於未匹配到的情況,通常放最後。

以身作則 以身作則 Jul 29, 2025 am 04:10 AM

Go泛型從1.18開始支持,用於編寫類型安全的通用代碼。 1.泛型函數PrintSlice[Tany](s[]T)可打印任意類型切片,如[]int或[]string。 2.通過類型約束Number限制T為int、float等數字類型,實現Sum[TNumber](slice[]T)T安全求和。 3.泛型結構體typeBox[Tany]struct{ValueT}可封裝任意類型值,配合NewBox[Tany](vT)*Box[T]構造函數使用。 4.為Box[T]添加Set(vT)和Get()T方法,無需

以示例運行子過程 以示例運行子過程 Aug 06, 2025 am 09:05 AM

使用os/exec包運行子進程,通過exec.Command創建命令但不立即執行;2.使用.Output()運行命令並捕獲stdout,若退出碼非零則返回exec.ExitError;3.使用.Start()非阻塞啟動進程,結合.StdoutPipe()實時流式輸出;4.通過.StdinPipe()向進程輸入數據,寫入後需關閉管道並調用.Wait()等待結束;5.必須處理exec.ExitError以獲取失敗命令的退出碼和stderr,避免殭屍進程。

您如何與Golang的環境變量合作? 您如何與Golang的環境變量合作? Aug 19, 2025 pm 02:06 PM

Goprovidesbuilt-insupportforhandlingenvironmentvariablesviatheospackage,enablingdeveloperstoread,set,andmanageenvironmentdatasecurelyandefficiently.Toreadavariable,useos.Getenv("KEY"),whichreturnsanemptystringifthekeyisnotset,orcombineos.Lo

GO應用程序的標準項目佈局是什麼? GO應用程序的標準項目佈局是什麼? Aug 02, 2025 pm 02:31 PM

答案是:Go應用沒有強制項目佈局,但社區普遍採用一種標準結構以提升可維護性和擴展性。 1.cmd/存放程序入口,每個子目錄對應一個可執行文件,如cmd/myapp/main.go;2.internal/存放私有代碼,不可被外部模塊導入,用於封裝業務邏輯和服務;3.pkg/存放可公開復用的庫,供其他項目導入;4.api/可選,存放OpenAPI、Protobuf等API定義文件;5.config/、scripts/、web/分別存放配置文件、腳本和Web資源;6.根目錄包含go.mod和go.sum

如何從GO中築巢的循環中斷 如何從GO中築巢的循環中斷 Jul 29, 2025 am 01:58 AM

在Go中,要跳出嵌套循環,應使用標籤化break語句或通過函數返回;1.使用標籤化break:將標籤置於外層循環前,如OuterLoop:for{...},在內層循環中使用breakOuterLoop即可直接退出外層循環;2.將嵌套循環放入函數中,滿足條件時用return提前返回,從而終止所有循環;3.避免使用標誌變量或goto,前者冗長易錯,後者非推薦做法;正確做法是標籤必須位於循環之前而非之後,這是Go語言中跳出多層循環的慣用方式。

See all articles