カテゴリ: Go言語 更新日: 2025/12/10

Go言語のdefer・panic・recoverを使ったエラーハンドリング例!初心者でもわかる安全なプログラムの作り方

Go言語のdefer・panic・recoverを使ったエラーハンドリング例
Go言語のdefer・panic・recoverを使ったエラーハンドリング例

先生と生徒の会話形式で理解しよう

生徒

「先生、Go言語でプログラムが急に止まったときに使う panic と、止まらずに続けられるようにする recover、そして最後に必ず処理を実行する defer ってどう使うんですか?」

先生

「いい質問ですね。deferpanicrecoverはGo言語の中で特別な仕組みで、エラーやトラブルを安全に扱うための重要な道具です。これらを組み合わせることで、問題が起きてもプログラムを急に止めずに、きちんと処理を終わらせることができるんですよ。」

生徒

「なるほど。具体的にどうやって使うか例を見せてください!」

先生

「では、実際に簡単な例を使って説明しますね!」

1. defer・panic・recoverとは?

1. defer・panic・recoverとは?
1. defer・panic・recoverとは?

defer(ディファー)は、関数の最後に必ず実行したい処理を書くときに使います。たとえばファイルを開いた後、必ず閉じる処理を忘れないようにするために使います。

panic(パニック)は、プログラムがどうしても続けられない重大なエラーが起きたときに使います。プログラムを一時的に停止させて、問題を知らせます。

recover(リカバー)は、panicで止まりかけたプログラムを助けて、急停止せずに続けられるようにする仕組みです。

2. defer・panic・recoverを使ったエラーハンドリングの例

2. defer・panic・recoverを使ったエラーハンドリングの例
2. defer・panic・recoverを使ったエラーハンドリングの例

次のコードは、Go言語でdefer、panic、recoverを使ってエラー処理を安全に行う例です。


package main

import "fmt"

// 危険な処理をする関数
func riskyFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("panicをrecoverしました:", r)
        }
    }()

    fmt.Println("riskyFunction開始")

    // ここでpanic発生
    panic("何か重大なエラーが起きました!")

    // この行は実行されません
    fmt.Println("riskyFunction終了")
}

func main() {
    fmt.Println("プログラム開始")
    riskyFunction()
    fmt.Println("プログラムは停止せずに続いています")
}

この例では、riskyFunctionの中でpanicが発生しますが、deferで登録した無名関数が実行され、recoverでpanicを捕まえています。

そのため、プログラムは停止せずに続き、「プログラムは停止せずに続いています」が表示されます。

3. deferで遅延処理を登録する理由

3. deferで遅延処理を登録する理由
3. deferで遅延処理を登録する理由

deferを使うことで、関数の処理がどう終了しても必ず指定した処理が実行されます。たとえば、ファイルを開いた後に必ず閉じる処理、ロックを解除する処理などに使います。

panicが起きて関数の途中で処理が止まっても、deferは実行されるため、リソースの解放や後片付けが安全に行えます。

Go言語を基礎からスッキリ学びたい人や、 文法だけでなく「実用的な使い方」まで押さえたい人には、 定番の入門書がこちらです。

基礎からわかるGo言語をAmazonで見る

※ Amazon広告リンク

4. panicとrecoverを使う時の注意点

4. panicとrecoverを使う時の注意点
4. panicとrecoverを使う時の注意点
  • recoverは必ずdeferされた関数内で呼ぶ必要があります。普通の関数内で呼んでも効果がありません。
  • panicは基本的にプログラムを止めるための仕組みなので、通常はerror型を返すエラー処理を優先しましょう。
  • panicとrecoverは例外的な状況やライブラリの内部処理で使われることが多いです。

5. panicが起きたときのプログラムの流れ

5. panicが起きたときのプログラムの流れ
5. panicが起きたときのプログラムの流れ

panicが発生すると、現在の関数は即座に処理をやめて呼び出し元に戻ります。呼び出し元でもpanic処理が続き、関数呼び出しの履歴(スタック)をさかのぼっていきます。

このとき、戻っていく途中に登録されたdefer関数が実行されます。その中でrecoverが呼ばれるとpanicを止めてプログラムを続けられます。

6. ポイント整理

6. ポイント整理
6. ポイント整理

Go言語のdeferpanicrecoverは、プログラムの流れを守りながらエラーに対応するための基本的な道具です。たとえば、deferは「必ず実行してほしい後片付け」を置く場所として便利で、ファイルを閉じたり、処理の終了を記録したりと、さまざまな場面で役立ちます。panicは重大な問題が起きたことを知らせる最後の手段で、recoverはその慌ただしい状態から落ち着きを取り戻すための仕組みです。

特に初心者の方は、これらが難しそうに見えるかもしれませんが、基本的な考え方を理解しておくと応用しやすくなります。たとえば次のような、単純な例を想像してみてください。


func sample() {
    defer fmt.Println("最後にかならず実行されます")
    panic("予期しない問題が発生しました")
}

この短いサンプルでも、panicが発生して関数の途中で止まったとしても、deferで登録された処理がきちんと実行されることがわかります。こうした仕組みのおかげで、プログラムは予期せぬ問題が起きても必要な処理を確実に残せます。

それぞれの役割を正しく理解して使うことで、プログラム全体の信頼性が高まり、思わぬ停止を避けながら安定した動作を保つことができます。

まとめ

まとめ
まとめ

defer・panic・recoverの仕組みを踏まえた安全な処理の考え方

Go言語におけるdeferpanicrecoverは、単にエラーを扱うための道具にとどまらず、処理の流れを制御しながら安全なプログラムを保つための重要な仕組みです。特に、複雑な処理が積み重なる場面や、外部との接続が関わる場面では、予期しない状態からの復旧や、最終処理の確実な実行が欠かせません。deferは関数の終了時に必ず動作させるべき片付け処理を保証し、panicは重大な失敗を知らせ、recoverはその失敗から立ち直るための柔軟な仕組みを提供します。 また、panicが起きた瞬間に現在の関数が実行を停止し、次々と呼び出し元へと戻っていく際、そこに積み重なっているdeferが順に実行されるため、構造を理解した設計がとても重要になります。ファイル操作、ネットワーク接続、データベース処理といった場面では後片付けが必須であり、deferがその役割を自然に担います。 初心者のうちは、panicrecoverに頼りすぎてしまうこともありますが、実際には日常的なエラー処理ではerror型を返す手法が一般的です。panicは想定外の条件を通知するための特別な道具であり、適切な使いどころを見極めることが重要です。recoverは必ずdefer内で呼ばれる必要があるという仕組みを理解しておくことで、想定外の停止を回避しながら柔軟に処理を続けることができます。

defer・panic・recoverを組み合わせた応用例

下記のコードでは、記事で紹介されている内容を踏まえながら、複雑な処理の中で予期しないエラーを回避しつつ、後片付けを確実に実行する仕組みを示しています。特に、複数の関数が連続する処理では、どこで重大な問題が発生しても、共通の片付け処理が確実に行われることが望まれます。


package main

import (
    "fmt"
)

// リソースを扱う模擬関数
func useResource() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recoverで異常を捕まえました:", r)
        }
        fmt.Println("後処理を必ず実行します")
    }()

    fmt.Println("リソース処理を開始します")

    // 想定外のエラー
    panic("重大なリソースエラーが発生しました")

    // この行は実行されません
    fmt.Println("リソース処理を終了します")
}

func main() {
    fmt.Println("メイン処理開始")
    useResource()
    fmt.Println("プログラムは継続して動作しています")
}

このように、panicによる強制的な停止が起きても、deferによって登録された処理が実行され、recoverによって復旧が行われるため、プログラム本体の流れが維持されます。特に運用環境では、予想外の異常が発生してもサービス全体を停止させないように設計することが求められます。そのため、こうした仕組みを理解し、適切に組み合わせて使うことで、安全性と安定性を兼ね備えたシステムを構築できます。

defer・panic・recoverが支える安定した処理設計

Go言語を学ぶ際、これらの仕組みは難しく感じられることもありますが、実際には非常に自然な流れで組み立てられています。関数が終わるときに必ず実行すべき片付けをdeferで書き、どうしても続行できないときにpanicで知らせ、必要に応じてrecoverで落ち着かせる。この一連の流れは、現実世界でのトラブル対応に近い考え方ともいえます。 例えば、作業中に問題が起きても、後処理をしないまま放置してしまえばさらなるトラブルにつながります。Go言語では、こうした状況を避けるための自然な枠組みが整っており、理解して使いこなすことで、より堅牢で信頼性の高いプログラムを書くことができるようになります。複雑な処理を分かりやすく整理するための設計にも応用できるため、今後の学習や実務の中で幅広く役立ちます。

先生と生徒の振り返り会話

生徒

「きょう学んだdefer・panic・recoverの流れがとても理解しやすかったです。どの場面で使うべきかもイメージできました。」

先生

「良い気づきですね。特にdeferは日常的に役立つ仕組みなので、ファイル操作や後片付けが必要な場面では積極的に活用してください。」

生徒

「panicとrecoverは特別な場面で使うという点も勉強になりました。無闇に使うと逆にわかりづらくなるんですね。」

先生

「その通りです。使いどころを見極めたり、正しい構造の中で組み合わせたりすることで、安全で読みやすいコードになります。ぜひ今回の理解を今後のプログラムでも活かしてくださいね。」

関連記事:
カテゴリの一覧へ
新着記事
New1
Go言語
Go言語の構造体の初期化パターンとコンストラクタ的関数の書き方を徹底解説!初心者でもわかる基本と実用例
New2
Kotlin
Kotlinの例外処理とキャンセルの連携を完全ガイド!初心者でもわかるCoroutineExceptionHandlerの使い方
New3
Go言語
Go言語のクロージャとは?関数内関数の活用例と仕組み
New4
Swift
Swiftでエラー原因を可視化!ログとトレースのベストプラクティスを初心者向けに解説
人気記事
No.1
Java&Spring記事人気No1
Kotlin
KotlinのChannelでデータをやり取りする方法を完全ガイド!初心者にもわかる非同期通信の基本
No.2
Java&Spring記事人気No2
Go言語
Go言語でのDB接続情報を環境変数で管理する方法|初心者でも安全に設定
No.3
Java&Spring記事人気No3
Kotlin
Kotlinのビルド設定エラーと解決法まとめ!初心者向けGradleトラブル対処ガイド
No.4
Java&Spring記事人気No4
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.5
Java&Spring記事人気No5
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.6
Java&Spring記事人気No6
Kotlin
Kotlinでテキスト表示・編集!初心者でもわかるTextViewとEditTextの使い方
No.7
Java&Spring記事人気No7
Go言語
Go言語のgo.modファイル完全ガイド!初心者でもわかる仕組みと書き方
No.8
Java&Spring記事人気No8
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方

💻 作業効率アップに

ノートPCを縦置きしてデスクを広く。
省スペースで片づく定番スタンド

UGREEN 縦型スタンドをAmazonで見る

※ Amazon広告リンク