カテゴリ: Go言語 更新日: 2026/03/05

Go言語のdefer・panic・recoverを使って安全なコードを書こう!初心者にもわかりやすく解説

Go言語のdefer・panic・recoverを活用した安全なコード例
Go言語のdefer・panic・recoverを活用した安全なコード例

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

生徒

「Go言語で、プログラムがエラーで止まっちゃうのを防ぐ方法ってありますか?」

先生

「はい、Go言語では deferpanicrecover を使って、エラー(異常な動作)から回復できるようにする仕組みがあります。」

生徒

「それって難しそうに聞こえるんですけど、初心者でも使えるんですか?」

先生

「もちろんです!身近な例えで説明しながら、一つずつ丁寧に見ていきましょう。」

1. defer(ディファー)とは?処理を後回しにする仕組み

1. defer(ディファー)とは?処理を後回しにする仕組み
1. defer(ディファー)とは?処理を後回しにする仕組み

deferは、「ある処理を最後に実行したいとき」に使うキーワードです。たとえば、お皿を洗う前に料理をして、最後に片付けをするような流れと似ています。

実際のプログラムでは、「ファイルを開いた後に閉じる」といった場面で活用されます。

以下は、deferの基本的な使い方です。


package main

import "fmt"

func main() {
    fmt.Println("処理開始")
    defer fmt.Println("最後の処理")
    fmt.Println("処理中")
}

このプログラムを実行すると、次のような順番で表示されます。


処理開始
処理中
最後の処理

deferで指定した処理は、関数の最後に実行されるので、main()関数の最後でfmt.Println("最後の処理")が動きます。

2. panic(パニック)とは?プログラムを途中で止める

2. panic(パニック)とは?プログラムを途中で止める
2. panic(パニック)とは?プログラムを途中で止める

panicは、重大なエラーが起きたときに、プログラムをすぐに止めるために使います。

たとえば、電子レンジのドアが開いたまま加熱しようとすると、すぐにエラーで止まるような仕組みです。

以下は、panicの使い方の例です。


package main

import "fmt"

func main() {
    fmt.Println("処理開始")
    panic("エラー発生!強制終了します")
    fmt.Println("この行は実行されません")
}

panicが実行されると、その時点でプログラムは停止し、それ以降の処理は動きません。

3. recover(リカバー)とは?panicから回復する方法

3. recover(リカバー)とは?panicから回復する方法
3. recover(リカバー)とは?panicから回復する方法

recoverは、panicで止まったプログラムを、途中で回復(リカバリー)させるために使います。

たとえば、車で急にタイヤがパンクしても、スペアタイヤで走り続けられるようなイメージです。

recoverは、deferとセットで使う必要があります。


package main

import "fmt"

func main() {
    fmt.Println("処理開始")

    defer func() {
        r := recover()
        if r != nil {
            fmt.Println("エラーを回復しました:", r)
        }
    }()

    panic("予期せぬエラー")
    fmt.Println("この行は実行されません")
}

このようにrecover()を使うと、panic()の後でもプログラムを途中で止めず、落ち着いてエラー処理ができます。

4. defer・panic・recoverの組み合わせで安全なコードに

4. defer・panic・recoverの組み合わせで安全なコードに
4. defer・panic・recoverの組み合わせで安全なコードに

この3つの機能を組み合わせると、Go言語でとても安全なプログラムを書くことができます。

次の例は、panicが発生してもrecoverで回復し、deferで後片付けまでしてくれるコードです。


package main

import "fmt"

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("安全に復旧:", r)
        }
    }()

    fmt.Println("処理を開始します")
    panic("問題発生")
    fmt.Println("ここには到達しません")
}

func main() {
    fmt.Println("メイン関数開始")
    safeFunction()
    fmt.Println("メイン関数終了")
}

このように、安全な関数を作ることで、他の処理に影響を与えずにエラー処理ができるようになります。

5. エラー処理のないコードとの違いを比べてみよう

5. エラー処理のないコードとの違いを比べてみよう
5. エラー処理のないコードとの違いを比べてみよう

以下は、recoverを使わなかった場合の例です。プログラム全体が停止してしまうのがわかります。


package main

import "fmt"

func main() {
    fmt.Println("処理開始")
    panic("予期せぬエラー")
    fmt.Println("この行は実行されません")
}

処理開始
panic: 予期せぬエラー

goroutine 1 [running]:
main.main()
        .../main.go:6 +0x39

これに対して、recoverを使えば次のように表示され、プログラムの残りの処理も安全に実行できます。


処理開始
安全に復旧: 予期せぬエラー
メイン関数終了

6. deferの注意点と複数使用時の順番

6. deferの注意点と複数使用時の順番
6. deferの注意点と複数使用時の順番

deferは複数回使うことができますが、呼び出された順番とは逆に実行される点に注意しましょう。これを「スタック構造(後入れ先出し)」といいます。


package main

import "fmt"

func main() {
    defer fmt.Println("後")
    defer fmt.Println("中")
    defer fmt.Println("前")
}

前
中
後

このように、最後に登録されたdeferが最初に実行されます。

まとめ

まとめ
まとめ

Go言語の特徴的な仕組みである deferpanicrecover は、ただのエラー処理テクニックではなく、安全なプログラムを構築するうえで欠かせない強力な機能です。今回の記事では、初心者でも直感的に理解できるように、日常の例えを交えながらひとつずつ丁寧に解説してきました。

まず defer は、「最後に必ず実行したい処理」を登録しておくための仕組みで、ファイルのクローズ処理や後片付けのような場面でとても役に立ちます。関数の終わりに安全に後処理を差し込めるため、コードを整理するうえでも重要な要素になります。また、複数の defer が積み重なった場合には、後から登録されたものが先に実行されるというスタック構造になる点も、理解しておくとさらに応用が効きます。

一方で panic は、重大な異常が発生したときにプログラムを強制停止させる動作という位置づけで使われるもので、意図せず起こった問題に対して早期に処理を中断させる機能です。普段の開発では頻繁に使うものではありませんが、異常を検知した際に「そのまま進むと危険」という状況で確実に停止させたいケースなどでは、その役割が非常に有効です。

そして recover は、 panic によって停止しかけたプログラムを安全に回復させるための仕組みで、特にエラーハンドリングを柔軟に行いたいときに威力を発揮します。recover は単体では働かず、defer と一緒に使うことで、panic の情報を受け取りながら回復処理を行います。この3つを組み合わせた構造は、Go言語特有のエラー処理モデルであり、より実践的なコードの中で頻繁に使われるパターンです。

特に大切なのは、「普段は正常に動くプログラムでも、異常が起こる場面は必ず存在する」という前提をもって安全性の高い処理を書くことです。ファイル操作、ネットワーク通信、外部APIとの連携など、いつ予期せぬ状態になるかわからない部分を適切に守るためには、deferpanicrecover をしっかり理解しておく必要があります。ここからは、この3つをさらに応用的に活用する追加サンプルを紹介し、実際の現場で使える知識として定着させていきましょう。

追加サンプルコード:ファイル処理とpanicの回復


package main

import (
    "fmt"
    "os"
)

func readFile(path string) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("エラーから復旧:", r)
        }
    }()

    file, err := os.Open(path)
    if err != nil {
        panic("ファイルを開けませんでした")
    }
    defer file.Close()

    fmt.Println("ファイルの読み込みに成功しました")
}

func main() {
    fmt.Println("処理開始")
    readFile("not_exists.txt")
    fmt.Println("処理継続")
}

このコードでは、存在しないファイルを開こうとした瞬間に panic が発生しますが、recover が正しく組み込まれているため、プログラムが完全に停止することなく「処理継続」まで実行されます。deferfile.Close() を確実に実行するようにしている点も安全性を助ける重要な部分です。現実のプログラムでも、ファイルのクローズを忘れてしまうとリソースの漏れにつながるため、defer の活用は非常に意味があります。

また、このように panicrecover による異常時の制御は、複雑な処理の中でも役立つため、初心者のうちからその流れに慣れておくことは大きなメリットになります。ログの記録や通知処理を追加すれば、さらに実務で通用する仕組みへと発展させることができます。Go言語ならではのエラー処理スタイルを理解しておくと、堅牢なアプリケーションを作る際に役立つ場面が必ず訪れるでしょう。

プログラムが突然止まってしまうような事態を未然に防ぎ、異常時にも正常終了へ導けるような仕組みは、まさに信頼性を高めるための重要な鍵です。今回の学びを踏まえ、これからのGo言語での開発の中でぜひ積極的に活用してみてください。

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

生徒

「defer・panic・recover の3つがどんな役割なのか、だいぶ理解できました!」

先生

「とても良いですね。特に recover を defer の中で使う流れを覚えれば、安全なエラー処理を書けるようになりますよ。」

生徒

「追加のサンプルみたいに、ファイルを開けなかった時に panic しても、recover が受け止めてくれるのは頼もしいですね!」

先生

「その通りです。Go言語はシンプルなエラーハンドリングが特徴ですが、panic が必要な場面もあります。ただしむやみに使うのではなく、recover と合わせて安全に扱うことが大切です。」

生徒

「はい!これからはエラーが起きても止まらないプログラムを書けるように練習してみます!」

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

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

※ Amazon広告リンク

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

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

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

Go言語のdeferとは何ですか?どんな場面で使うのですか?

Go言語のdeferは、関数の最後に実行したい処理を登録するキーワードです。たとえば、ファイルを開いた後に必ず閉じたい場合など、安全な後処理に使います。

Go言語でpanicとは何を意味しますか?

panicはGo言語で重大なエラーが発生したときに、プログラムを即座に停止させるために使います。安全に処理できない異常時に利用される仕組みです。
関連セミナーのご案内

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

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

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

具体的な開発内容と環境

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

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

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

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

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

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

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

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

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

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

セミナー画像

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

カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のwhile的なforループの使い方!条件式ループの基本を解説
New2
Go言語
Go言語プログラムの実行方法まとめ!VSCode・ターミナルでの実行手順を解説
New3
Swift
Swift意味とは?プログラミング言語・金融・鳥の違いを徹底解説
New4
Swift
Swift 戻り値の扱い方と複数戻り値の返し方|初心者でも分かる関数の基本
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語でリダイレクト処理を行う方法(http.Redirect)を初心者向けに解説
No.2
Java&Spring記事人気No2
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.3
Java&Spring記事人気No3
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Go言語
Go言語のgo.modファイル完全ガイド!初心者でもわかる仕組みと書き方
No.6
Java&Spring記事人気No6
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.7
Java&Spring記事人気No7
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説
No.8
Java&Spring記事人気No8
Go言語
Go言語で条件式を1行で書くコツ!三項演算子の代替と短縮記法