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が「遅延実行」し、関数終了時にスタックからポップされるという仕組みです。これを理解すれば、クリーンアップコードを安全かつ簡潔に書くことができます。
コメント
コメントを投稿