👨‍💻簡介

當我們在寫程式時,有時候會需要在程式結束時關閉某些資源,而defer這個關鍵字,可以讓你輕鬆的實現,下面來簡單介紹一下defer以及常用的範例。,它為程式設計師提供了一種簡單而強大的工具,用於管理資源和確保程式的正確執行。在本篇文章中,我們將深入探討Go語言中的defer,並提供一些實際的程式碼範例,以幫助你理解它的工作原理以及如何運用它來提高程式的可讀性和可維護性。

什麼是defer

defer是一個關鍵字,用來延遲函數的執行,直到包含它的函數執行完畢。這代表你可以在函數中的任何位置使用defer來安排某個操作,並確保它將在函數返回之前執行。defer通常用於執行一些清理或資源回收的操作。

package main

import "fmt"

func main() {
    defer fmt.Println("World")
    fmt.Print("Hello, ")
}

使用方式也很簡單,在要執行的函數前面加上defer就完成了,所以上面的範例會印出 Hello World

Defer的特性

  1. 延遲執行defer 語句允許你安排一段程式碼,使它在包含它的函數返回之前執行,無論函數是否正常返回或出現錯誤。

  2. 堆疊特性:多個 defer 語句按照後進先出(LIFO)的順序執行,這意味著最後一個被延遲的語句會最先執行。

package main

import "fmt"

func main() {
    fmt.Println("Start")
    defer fmt.Println("Deferred 1")
    defer fmt.Println("Deferred 2")
    fmt.Println("End")
}

根據defer特性的後進先出,輸出會是下面這個樣子

Start
End
Deferred 2
Deferred 1

Defer的限制

  1. 延遲的函數必須是無參數函數:你只能延遲無參數的函數調用,因為 defer 不允許傳遞參數。

  2. 順序性defer 語句的效果在函數內是有限定範圍的,它只在包含它的函數範圍內有效,無法跨函數使用。

常見用法

資源清理

最常見的用途之一是在函數返回前關閉文件、釋放鎖、關閉資料庫連接等,以確保資源被正確釋放。

func readFile(filename string) (string, error) {
    file, err := os.Open(filename)
    if err != nil {
        return "", err
    }
    defer file.Close()
    
    // 讀取文件內容
    // ...
    
    return content, nil
}

在上述範例中,defer 用於確保文件在函數返回之前被正確關閉。

記錄錯誤

**:defer 可以用於處理錯誤,例如記錄錯誤訊息或回滾交易,並確保它們不會被遺漏。

func doSomething() error {
    err := performOperation()
    if err != nil {
        defer logError(err)
    }
    
    // 其他操作
    return nil
}

func logError(err error) {
    fmt.Println("Error:", err)
}

在上述範例中,defer 用於記錄錯誤,無論函數是否正常返回。

小結

defer是Go語言中一個強大的功能,通常在撰寫對db的連接時我都會在下一行使用defer進行db的關閉連接,確保這些操作在函數返回之前執行。這使得程式更容易閱讀和維護,並有助於避免資源洩漏等問題,它可用於資源管理、錯誤處理和性能優化等多種情況下,提高程式的可讀性和可維護性。

📚Reference