カテゴリ: Go言語 更新日: 2026/04/15

Go言語のpanicとrecoverの基本!エラーハンドリングの応用例

Go言語のpanicとrecoverの基本!エラーハンドリングの応用例
Go言語のpanicとrecoverの基本!エラーハンドリングの応用例

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

生徒

「Go言語でプログラムが急に止まってしまうことがあるって聞いたんですが、どういうことですか?」

先生

「それはpanic(パニック)という仕組みが働いたときのことですね。プログラムに深刻な問題が起きたときに、実行を強制的に止める機能です。」

生徒

「そのまま止まると困ります。途中でなんとかできないんですか?」

先生

「そんなときにはrecover(リカバー)を使うと、プログラムの途中でエラーを回避して処理を続けることができます。それでは、基本からわかりやすく説明していきましょう。」

1. panicとは?Go言語で発生する致命的なエラー

1. panicとは?Go言語で発生する致命的なエラー
1. panicとは?Go言語で発生する致命的なエラー

panicは、Go言語の実行時に「もう続けられない」と判断された致命的な状況で起きる仕組みです。発生するとその場で処理が中断され、プログラムは強制終了します。いわば「非常停止ボタン」で、通常のエラーチェック(戻り値のerror)では扱わない想定外のバグや環境異常を知らせます。

自動で起きる例としては、配列やスライスの範囲外アクセス、ゼロ除算、初期化されていない値の誤用などがあります。開発者が明示的にpanicを呼び出して、続行不能な初期化失敗などを通知することもできます。


package main

func main() {
    panic("重大なエラーが発生しました") // 明示的に非常停止させる
}

このコードを実行すると、「重大なエラーが発生しました」というメッセージと共に、処理はそこで止まります。停止時には「どこで止まったか」を示す情報(スタックトレース)が出力されるため、原因の追跡に役立ちます。

初心者向けの簡単な例:範囲外アクセスで自動的にpanic

次は、スライスの要素数を超えてアクセスしたために、Goランタイムが自動でpanicを起こす例です。意図せず境界を超えると、強制終了して不正な処理の拡大を防ぎます。


package main

import "fmt"

func main() {
    nums := []int{10, 20, 30}
    fmt.Println(nums[3]) // 要素は0,1,2まで。3は範囲外なのでpanic
}

panic: runtime error: index out of range

ポイントは、「通常の失敗はerrorで返す」「どうしても続けられない異常だけpanic」という住み分けです。これを意識すると、Go言語のエラーハンドリングがぐっと読みやすく、保守しやすくなります。

2. recoverとは?panicから回復する仕組み

2. recoverとは?panicから回復する仕組み
2. recoverとは?panicから回復する仕組み

recoverは、panicで「非常停止」しかけた処理をその場で受け止め、プログラムの強制終了を避けるための関数です。重要なのは、recoverdefer(ディファー)内で呼び出したときだけ有効という点です。関数の終わりに必ず実行されるdeferと組み合わせることで、発生したpanicの情報(文字列やエラー)を受け取り、ログを残したり安全に片付け処理をしてから復帰できます。

はじめての方向けに、最小の例を用意しました。panicをわざと起こし、defer内の無名関数でrecoverしてメッセージを表示します。


package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {          // panicの内容を受け取る
            fmt.Println("回復しました:", r)     // ここで記録・後始末などが可能
        }
    }()

    fmt.Println("処理を開始します")
    panic("ファイルが見つかりません")          // ここで非常停止相当の事態が発生
    fmt.Println("この行は実行されません")        // recover前なので到達しない
}

処理を開始します
回復しました: ファイルが見つかりません
よくあるつまずき:deferの外で呼んでも効かない

recoverを通常の位置(deferの外)で呼んでも、panicは止まりません。必ずdefer内で使いましょう。


package main

func main() {
    // recover() をここで呼んでも効果なし
    panic("範囲外アクセス") // 強制終了してしまう
}

まとめると、recoverは「panicの情報を受け取り、終了前に態勢を立て直すための最後の受け皿」。deferとセットで使う、というルールだけまず覚えておけば、入門段階のエラーハンドリングで十分に役立ちます。

3. defer(ディファー)とは?処理を最後に実行する仕組み

3. defer(ディファー)とは?処理を最後に実行する仕組み
3. defer(ディファー)とは?処理を最後に実行する仕組み

deferは「この関数が終わる直前に必ず実行してね」という予約です。正常終了でもreturnによる早期終了でも、関数を抜ける瞬間に実行されます。後片付け(ファイルを閉じる、ロック解除、タイマー停止など)を、見通しよく一か所にまとめられます。

まずは最小の例。宣言した順ではなく逆順(LIFO)で動くことに注目してください。


package main

import "fmt"

func main() {
    defer fmt.Println("3) 最後に実行されます")
    defer fmt.Println("2) その前に実行されます")
    fmt.Println("1) 最初に表示されます")
}

1) 最初に表示されます
2) その前に実行されます
3) 最後に実行されます
ポイント:引数は「その場で」評価、関数本体は「あとで」実行

deferに渡す関数の引数は予約した瞬間に評価され、関数呼び出し自体は終了時に行われます。数値が変わっても、評価済みの値が使われます。


package main

import "fmt"

func main() {
    x := 10
    defer fmt.Println("xの値:", x) // ここで x=10 が固定される
    x = 99
    fmt.Println("現在のx:", x)
}

現在のx: 99
xの値: 10
現場でよく使う形:後始末を確実にする

実務では、取得したリソースを確実に解放する用途が定番です。次の例では「開始」と表示した後、関数終了時に必ず「終了」と出力されます。途中でreturnしても実行されるため、片付け漏れを防げます。


package main

import "fmt"

func work() {
    fmt.Println("処理を開始")
    defer fmt.Println("後片付け:処理を終了")
    // ここで早期returnしても、上のdeferは必ず実行される
    return
}

func main() {
    work()
}

処理を開始
後片付け:処理を終了

まとめると、deferは「関数を出る際の安全網」。逆順で実行され、引数は登録時に評価されます。片付けの定位置として覚えておくと、コードは読みやすく、ミスも減らせます。

4. panicとrecoverの組み合わせによる実用例

4. panicとrecoverの組み合わせによる実用例
4. panicとrecoverの組み合わせによる実用例

例えば、ファイルを読み込む関数で予期せぬ問題が発生したときでも、プログラムを止めずに対応する方法として、panicとrecoverを組み合わせることができます。


func safeDivide(a, b int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("エラー:", r)
        }
    }()

    if b == 0 {
        panic("0で割ることはできません")
    }

    fmt.Println("結果:", a/b)
}

func main() {
    safeDivide(10, 2)
    safeDivide(5, 0)
    fmt.Println("プログラムは継続しています")
}

結果: 5
エラー: 0で割ることはできません
プログラムは継続しています

このように、panicとrecoverを使うことで、安全に処理を続行することが可能になります。

5. panicとrecoverを使う際の注意点

5. panicとrecoverを使う際の注意点
5. panicとrecoverを使う際の注意点

便利なpanicとrecoverですが、乱用は禁物です。基本的なエラー処理(if err != nilなど)で対応できる場合は、panicではなく通常のエラーハンドリングを使うようにしましょう。

panicは本当に回避できないエラー、たとえばプログラムの設計に重大な欠陥があるときに使うべきです。

recoverも、すべてのpanicを抑えるのではなく、部分的に必要な場面で使うのがポイントです。

まとめ

まとめ
まとめ

Go言語のpanicとrecoverは、単純なエラーハンドリングでは対処できない深刻な問題に向きあうための大切な仕組みです。とくに実際の開発現場では、さまざまな入出力処理やネットワーク通信、予測できない外部サービスの停止などが起きるため、例外的な状況に落ち着いて対応できる知識が必要になります。通常のエラー処理はif文で確認できますが、実行中のどこかで取り返しがつかない状態になった場合、panicはとても強力に働きます。プログラムはただ停止するのではなく、呼び出し元へ向かって巻き戻し処理を行い、関数の終わりで必ず実行されるdeferに処理を引き渡すため、最後のチャンスとしてrecoverを使って状況を整えることができます。

安全なアプリケーションを作るには、panicを完全に避けるのではなく、panicが起きたときにどう戻すかを考えることが大切です。ファイルが突然読み込めなくなることも、予想外の計算ミスが起きることも、データが破損してしまうこともあります。そんな時、recoverはパニック状態を吸収して処理を継続し、ログやメッセージを残し、ユーザー体験を損なわない形に導いてくれます。同時に、むやみな乱用は避け、必要な箇所だけを冷静に守ることが重要です。

例えば、銀行処理や通販の注文処理のような「一部のタスクが失敗しても全体を止めてはいけない」場面では、panicとrecoverの組み合わせが信頼性を高めます。バックグラウンドで動く処理や大量のデータを扱う機能でも、安全に回復しながら処理を継続できます。もしクラッシュしてしまうと、ユーザーは安心して利用できず、業務の信頼性まで揺らいでしまいます。そのため、深刻な事態でも落ち着いてプログラムを存続させる仕組みとして、panicとrecoverは頼もしい存在になります。

さらに、テストの手法としても有効です。意図的にpanicを発生させて処理が正しく回復するかを確認できるため、自動テストで安全性を担保できます。また、ログやエラー情報を記録しておけば、あとから原因追及もしやすくなります。問題が起きた瞬間にすべての情報が消えてしまうのではなく、どこで何が起きたのかを把握して修正につなげることができます。

ここで、panicとrecoverをまとめて使う例をもう一度確認しましょう。下のサンプルでは、予期せぬ状況が起きても落ち着いて回復できる仕組みを実感できます。


func safeRunner() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("問題が起きたため処理を回復しました:", r)
        }
    }()
    panic("予期しない状態が発生しました")
}

この処理では、panicが発生してもrecoverが落ち着いて受け止め、ユーザーに状況を伝えつつプログラムを止めずに次の処理へ進めます。もしこの仕組みがなければ、プログラムは途中で崩壊し、画面には不親切なメッセージだけが残ってしまいます。Go言語はシンプルな構文の中に強力な仕掛けを備えているため、初心者でも少しずつ慣れていけば、堅牢なアプリケーションを作れるようになります。

まとめとして、panicは深刻な事態を知らせる手段であり、recoverはその状況を静かに受け止めて流れを整える存在です。deferはその橋渡しを行い、最後の瞬間に回復する余地を与えてくれます。エラー処理の幅は大きく広がり、安全管理の考え方も身につきます。日常的なシステム開発でも、ネットワーク接続、ファイル入出力、データ処理などで役立ちます。Go言語を使うなら、この仕組みをしっかり理解しておくと大きな安心につながります。

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

生徒

「panicとrecoverがあることで、急に止まる心配が減るんですね」

先生

「そうです。どんな言語でも安全性は大事ですが、Go言語はこの仕組みがとても扱いやすいのが強みです」

生徒

「もし失敗しても、ちゃんとメッセージを表示して続行できるのは安心ですね」

先生

「その通りです。panicは怖いわけではなく、問題を知らせる大切な合図なんです。recoverで受け止めれば、無理なく前へ進めますよ」

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

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

※ Amazon広告リンク

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Go言語でpanicとは何ですか?初心者でもわかるように教えてください

panicとは、Go言語で深刻なエラーが発生したときにプログラムを強制的に終了させる機能です。回避不能なバグや重大な異常処理に使われます。

Go言語のrecoverとは?panicと一緒に使う理由は何ですか?

recoverは、panicでプログラムが止まるのを防いで安全に回復させる機能です。panicと一緒に使うことで、エラー発生後も処理を継続できるようになります。
関連セミナーのご案内

【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導

「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。

本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。

具体的な開発内容と環境

【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。

【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。

この60分で得られる3つの理解

1. 環境構築の完全な理解

「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。

2. Go言語の基本構造(変数・型)

データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。

3. 読みやすいコードの書き方

ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。

※本講座は、将来的にバックエンドエンジニアクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。

セミナー画像

初めてのGo言語を一緒に学びましょう!

関連記事:
カテゴリの一覧へ
新着記事
New1
Kotlin
Kotlinの文字列を1文字ずつ処理する方法!for文とforEachの使い方を初心者向けに解説
New2
Kotlin
Kotlinの文字列比較の方法を徹底解説!==とcompareToの使い方を初心者向けにわかりやすく紹介
New3
Kotlin
Kotlinのrepeatメソッドの使い方を完全解説!初心者でもわかる文字列の繰り返し処理
New4
Kotlin
KotlinのisEmptyとisBlankの違いと使い方を徹底解説!初心者でもわかる文字列の空判定入門
人気記事
No.1
Java&Spring記事人気No1
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.2
Java&Spring記事人気No2
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.3
Java&Spring記事人気No3
Kotlin
Kotlinでテキスト表示・編集!初心者でもわかるTextViewとEditTextの使い方
No.4
Java&Spring記事人気No4
Kotlin
Kotlin Multiplatformライブラリの活用例と導入方法を初心者向けに解説!Android・iOS・Webを1つのコードで開発
No.5
Java&Spring記事人気No5
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.6
Java&Spring記事人気No6
Kotlin
Kotlinで定数を定義する方法!変更されない変数の書き方と命名ルール
No.7
Java&Spring記事人気No7
Go言語
Go言語でリダイレクト処理を行う方法(http.Redirect)を初心者向けに解説
No.8
Java&Spring記事人気No8
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド