MeWrite Docs

panic: runtime error

Goでpanicが発生した場合の原因と対処方法

概要

Goの panic は、プログラムが回復不能な状態に陥った場合に発生します。明示的に呼び出すこともでき、recover でキャッチしない限りプログラムがクラッシュします。

エラーメッセージ

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x...]
panic: runtime error: index out of range [5] with length 3
panic: assignment to entry in nil map

よくあるpanic

1. nilポインタ参照

1
2
var ptr *int
fmt.Println(*ptr) // panic: nil pointer dereference

2. 範囲外アクセス

1
2
arr := []int{1, 2, 3}
fmt.Println(arr[5]) // panic: index out of range

3. nilマップへの書き込み

1
2
var m map[string]int
m["key"] = 1 // panic: assignment to entry in nil map

4. 閉じたチャネルへの送信

1
2
3
ch := make(chan int)
close(ch)
ch <- 1 // panic: send on closed channel

5. 型アサーションの失敗

1
2
var i interface{} = "hello"
n := i.(int) // panic: interface conversion

解決策

1. nilチェック

1
2
3
4
5
6
func process(ptr *int) {
    if ptr == nil {
        return // または適切なエラー処理
    }
    fmt.Println(*ptr)
}

2. 境界チェック

1
2
3
4
5
6
func getElement(arr []int, index int) (int, error) {
    if index < 0 || index >= len(arr) {
        return 0, errors.New("index out of range")
    }
    return arr[index], nil
}

3. マップの初期化

1
2
3
4
5
6
7
// 宣言時に初期化
m := make(map[string]int)
m["key"] = 1

// または
m := map[string]int{}
m["key"] = 1

4. 型アサーションの安全版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var i interface{} = "hello"

// ok構文を使用
if n, ok := i.(int); ok {
    fmt.Println(n)
} else {
    fmt.Println("not an int")
}

// または type switch
switch v := i.(type) {
case int:
    fmt.Println("int:", v)
case string:
    fmt.Println("string:", v)
}

5. recoverでpanicをキャッチ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from:", r)
        }
    }()

    // panicを起こす可能性のあるコード
    panic("something went wrong")
}

func main() {
    safeFunction()
    fmt.Println("Program continues...") // 実行される
}

6. Webサーバーでのrecover

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func recoveryMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err := recover(); err != nil {
                log.Printf("panic: %v", err)
                http.Error(w, "Internal Server Error", 500)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

7. チャネルの安全な操作

1
2
3
4
5
6
7
8
9
func safeSend(ch chan int, value int) (sent bool) {
    defer func() {
        if recover() != nil {
            sent = false
        }
    }()
    ch <- value
    return true
}

panicを使うべき場面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 初期化時の致命的エラー
func init() {
    if os.Getenv("REQUIRED_VAR") == "" {
        panic("REQUIRED_VAR is not set")
    }
}

// プログラムのバグを示す場合
func mustCompile(pattern string) *regexp.Regexp {
    re, err := regexp.Compile(pattern)
    if err != nil {
        panic(err) // コンパイル時定数なのでエラーはバグ
    }
    return re
}

関連エラー

関連エラー

Go の他のエラー

最終更新: 2025-12-17