deferとは
関数が終了する直前に実行される処理を登録するためのGoのキーワード.
エラーハンドリングやリソースの解放等,後で必ず実行したい処理を指定するために用いられる.
defer
の基本仕様
構文: defer <関数呼び出し>
タイミング: defer
を指定した関数は,その関数が終了する直前に実行される.プログラム内で複数のdefer
を登録すると,後から登録したものが先に実行される(LIFO: 後入れ先出し).
defer
の用途
1. ファイルやネットワークリソースの解放: ファイルやデータベース接続,ネットワークリソースなど,使い終わったら閉じなければならないリソースを解放する際に使われる.
2. エラーハンドリング: パニック(異常終了)からのリカバリ(復旧)や,必ず実行するべき処理を定義する際に便利.
3. ロックやアンロック: 同時に実行されるプログラム(並行処理)でロックやアンロックを設定する場合,defer
でアンロックを後に予約しておくことで,誤ってロックを外し忘れるリスクを防げる.
具体例1
func example() {
defer fmt.Println("CleanUp!") // (1): deferでfmt.printlnを宣言
panic("Something terrible happened!") // (2): 強制終了
fmt.Println("Never reaches here") // (3): 実行されない
}
func main(){
defer ft.Println("main: CleanUp!") // (4)
example() // (5)
fmt.Println("Never reaches here") // (6)
}
出力例:
CleanUp!
main: CleanUp!
panic: Something terrible happened!
defer
が実行されないパターン
- プログラムが
os.Exit()
で強制終了される - OSからのsigkillシグナルでプログラムが強制終了される場合
- システムがクラッシュする場合
recover
関数について
Goにおいてパニック状態をキャッチして,プログラムが異常終了せず回復できるようにするための関数.
主にエラーハンドリングやプログラムの安定性を確保するために使われる.
recover
の仕様
使い方: defer
文内の関数のみ
戻り値:
-
if
panic
が発生していない then returnnil
-
if
panic
が発生している then return そのpanic
で渡された値
func example() {
defer func() {
if err := recover(); err!= nill {
fmt.Println("Recovered from panic:", err)
}
}()
panic("something went wrong") // パニックを発生させる
}
recover
の役割
1. パニックからの回復: panic
が発生すると通常はプログラムがクラッシュし,すべての処理が停止するが,recover
を使えばパニック状態から回復してプログラムを続行できる(異常終了を避け,エラー情報をログに残してから適切に処理を行うなど).
2. エラーメッセージの取得: panic
により送られたメッセージやエラーを取得することができるため,エラーの詳細を把握し,ログに出力したり,ユーザーにフィードバックを提供することができる.
3. 安定性の確保: サーバーやバッチ処理などで一部の処理がエラーになってもプログラム全体が停止しないようにすることができる.これによりプログラムの安定性が向上し,予期せぬエラーから復旧しやすくなる.
recover
を使ったエラーハンドリングの例
package main
import main
func riskyFunction() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic:", err)
}
}
fmt.Println("Start risky function")
panic("Something went wrong!") // パニックを発生
fmt.Println("This line will not be executed")// 実行されない
}
func main() {
fmt.Println("Program started")
riskFunction()
fmt.Println("Program continued after panic")
}
出力例:
Program started
Start risky function
Recovered from panic: Something wet wrong!
Program continued after panic