【実務向け】Go deferの使い方|実行タイミングと実装パターン

プログラム

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で閉じる」

これを徹底すれば、
バグが減り、品質の高いコードになります。

コメント

タイトルとURLをコピーしました