スキップしてメイン コンテンツに移動

deferでリソース解放

deferでリソース解放

defer文の基本

Go初心者にとって、deferは最初に触れるときに「遅延実行」や「関数終了時に実行される」というイメージが強いです。実際には、deferは関数の呼び出し時にスタックに保存され、関数が戻る直前に逆順で実行されます。これにより、リソース解放やクリーンアップ処理を簡潔に書くことができます。

例えば、ファイルを開いて読み込む場合、defer file.Close()と書くだけで、関数が終了するタイミングで必ずファイルが閉じられます。これがdeferの最大のメリットです。

スタックと実行順序

deferはスタックに積まれるため、複数のdeferがある場合は「後入れ先出し」の順序で実行されます。以下の例を見てみましょう。

func example() {
    defer fmt.Println("first")
    defer fmt.Println("second")
    defer fmt.Println("third")
}

この関数を呼び出すと、出力は

third
second
first

となります。つまり、deferは関数終了時に逆順で実行されるため、リソース解放の順序を意識する必要があります。特に、複数のリソースを開く場合は、後に開いたものを先に閉じるようにdeferを配置すると安全です。

実際のクリーンアップ例

以下は、データベース接続とファイル操作を同時に行うサンプルです。deferを使って、関数終了時に必ずクリーンアップできるようにしています。

func process() error {
    db, err := sql.Open("postgres", "connString")
    if err != nil {
        return err
    }
    defer db.Close() // データベース接続のクリーンアップ

    file, err := os.Open("data.txt")
    if err != nil {
        return err
    }
    defer file.Close() // ファイルのクリーンアップ

    // ここでデータベースとファイルを使った処理
    // ...

    return nil
}

このようにdeferを使うことで、エラーが発生しても関数が途中で抜けた場合でも、必ずリソース解放が行われます。Go初心者が最初に学ぶべきポイントは、deferが「遅延実行」し、関数終了時にスタックからポップされるという仕組みです。これを理解すれば、クリーンアップコードを安全かつ簡潔に書くことができます。

この記事はAIによって作成されました。

コメント