Go言語のdeferは、関数終了時に処理を実行するための重要機能です。
リソース管理やエラーハンドリングと組み合わせることで、安全で保守性の高いコードが書けます。
本記事では、deferの「使い方・タイミング・実装」を実務視点で解説します。
deferとは?
deferは、後で実行したい処理を予約するキーワードです。
defer fmt.Println("終了処理")
👉 この処理は即実行されず、
👉 関数が終了する直前に実行されます
実行タイミング(重要)
deferは必ず👇のタイミングで動きます
👉 関数のreturn直前
func main() {
defer fmt.Println("defer")
fmt.Println("start")
}
出力
start
defer
複数deferの挙動(LIFO)
複数書いた場合👇
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
出力
3
2
1
👉 後から書いたものが先に実行(スタック構造)
実務での使い方①:ファイルクローズ
file, err := os.Open("test.txt")
if err != nil {
return err
}
defer file.Close()
👉 開いた直後に書くのが鉄則
👉 書き忘れ防止
実務での使い方②:DB接続
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
defer db.Close()
👉 リソース解放は必須
👉 deferで安全に処理
実務での使い方③:ロック制御
mu.Lock()
defer mu.Unlock()
👉 エラー発生時も必ずUnlockされる
👉 並行処理では必須テクニック
よくあるミス
❌ 引数はdefer時に評価される
x := 1
defer fmt.Println(x)
x = 10
👉 出力は「1」
❌ ループ内deferは注意
for i := 0; i < 5; i++ {
defer fmt.Println(i)
}
👉 最後にまとめて実行
👉 メモリ消費増の原因になることも
ベストプラクティス
- リソース開放は必ずdefer
- 取得直後に書く
- ループ内で多用しない
- error処理と組み合わせる
エラーハンドリングとの組み合わせ
func readFile() error {
file, err := os.Open("test.txt")
if err != nil {
return err
}
defer file.Close()
return nil
}
👉
defer × error処理=Go実務の基本
まとめ
Goのdeferは👇がすべてです
- 関数終了時に実行
- LIFO(後入れ先出し)
- リソース管理に最適
- error処理とセットで使う
💡 結論
👉
「開いたらすぐdeferで閉じる」
これを徹底すれば、
バグが減り、品質の高いコードになります。


コメント