0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goの defer / panic / recover を理解する

0
Posted at

Goには try-catch のような例外構文はありません。

その代わりに、次の3つを組み合わせて 異常系と後始末 を扱います。

  • defer:関数終了時に必ず実行する処理
  • panic:致命的なエラーで処理を中断する
  • recoverpanic から復帰する(※ defer 内でのみ有効)

1. defer の基本動作

deferその関数が終了する直前 に実行されます。

funcTestDefer() {
defer fmt.Println("END")
	fmt.Println("START")
}

呼び出し:

TestDefer()

出力:

START
END

ポイント

  • return があっても defer は実行される
  • panic が起きても defer は実行される

2. defer は後始末に使う(ファイル操作)

Goでは、リソースを確保したら すぐに defer で解放処理を書くのが定石です。

file, err := os.Create("test.txt")
if err != nil {
	fmt.Println(err)
return
}
defer file.Close()

file.Write([]byte("Hello\n"))

なぜ defer なのか?

  • 途中で return しても必ず close される
  • エラーが増えても後始末を書き忘れにくい

👉 「open したらすぐ defer close」 はGoの鉄則

3. defer の実行順序(LIFO)

defer後に登録したものから先に実行されます。

fmt.Println("START")

defer fmt.Println("defer 1")
defer fmt.Println("defer 2")

fmt.Println("END")

出力:

START
END
defer 2
defer 1

👉 defer は スタック(LIFO)構造


4. panic とは?

panicプログラムを異常終了させる仕組みです。

panic("runtime error")

  • panic が呼ばれると通常の処理は中断される
  • その関数に登録された defer必ず実行される
  • 何も recover しなければプログラムは終了する

5. recover とは?

recover() は、発生した panic を捕まえて 処理を継続するための関数です。

超重要なルール

recover は defer の中で呼ばれたときだけ有効


6. panic / recover の正しい基本形

以下が panic を安全に recover する最小構成です。

package main

import"fmt"

funcmain() {
deferfunc() {
if x :=recover(); x !=nil {
			fmt.Println("recovered:", x)
		}
	}()

	fmt.Println("START")
panic("runtime error")
	fmt.Println("NEVER PRINT")
}

出力:

START
recovered: runtime error

処理の流れ

  1. defer が登録される
  2. panic が発生
  3. defer が実行される
  4. recover()panic を捕まえる
  5. main が正常終了する

7. panic が起きても defer は必ず実行される

panic が起きても、登録済みの defer はすべて実行されます。

defer fmt.Println("A")
defer fmt.Println("B")
panic("error")

出力:

B
A
panic: error

👉 そのため、recover を使わない場合でも

後始末(close / unlock など)は保証される


8. panic / recover の使いどころ

基本方針

  • 通常のエラー → error を返す
  • 想定外・不変条件違反 → panic
  • recover は アプリケーションの最上位層 で使うことが多い

例:

  • HTTPサーバのミドルウェア
  • goroutine の境界
  • main関数

9. まとめ

  • defer は関数終了時に必ず実行される
  • defer は後入れ先出し(LIFO)
  • ファイル操作など後始末に最適
  • panic は致命的な異常を表す
  • recoverdefer 内でのみ有効
  • panic が起きても defer は必ず実行される

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?