1
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について新たに学んだこと

Posted at

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 return nil
  • 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
1
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
1
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?