できない.dev

Go で「invalid memory address or nil pointer dereference」が解決できない

Go の runtime error: invalid memory address or nil pointer dereference は、nil のポインタやインタフェースに対してフィールドアクセス・メソッド呼び出しを行ったときに発生します。
代入直前に nil チェックを入れ、関数の戻り値で error を先に確認するのが基本対処です。

公開: 更新:

実行例あり(2026-09-08 に実環境で検証)

要約

panic: runtime error: invalid memory address or nil pointer dereference は、Go のポインタが nil のままフィールドアクセスやメソッド呼び出しをしたときに発生します。
多くは関数の戻り値で error を確認せずに使っているか、interface に nil のポインタを入れて != nil 判定が誤動作しているのが原因です。
使用直前で nil チェックを入れ、戻り値の規約を統一すれば大半は防げます。

実行例

初期化していないポインタを参照した最初の実行は invalid memory address or nil pointer dereference で panic し、go run が exit status 2 を報告して終了コードは 1 になった。
使用直前に nil を確かめる形へ変えると同じコードが終了コード 0 で通り、続く出力では、nil ポインタを interface に包んで返していたときに true だった err != nil が、untyped nil を返す書き方では false になっている。

$ go run .
u == nil: true
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x48f76d]
 
goroutine 1 [running]:
main.main()
	/tmp/tmp.gWJODeLnsg/main.go:12 +0x6d
exit status 2
終了コード: 1
$ go run .
process: user is nil
err != nil: true
終了コード: 0
$ go run .
process: user is nil
err != nil: false

— 2026-09-08 時点の出力

検証環境

検証日
実行環境
golang:1.23Debian GNU/Linux 12 (bookworm)
バージョン
  • Python 3.11.2
  • Git 2.39.5
  • Go 1.23.12

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 初期化していない var p *T をそのまま使っている
  2. func New() (*T, error) の戻り値で error を見ずに *T を呼び出している
  3. interface 値(例: var e error)に nil のポインタを代入しており、if e != nil が true になりながら中身は nil
  4. map[string]*Foo で未登録キーを引いて nil が返ったのに気付かず参照している

解決策

1. 使用直前で nil チェックする

func process(u *User) error {
    if u == nil {
        return fmt.Errorf("user is nil")
    }
    fmt.Println(u.Name)
    return nil
}

2. error を先に確認する

u, err := repo.FindByID(id)
if err != nil {
    return err
}
fmt.Println(u.Name)

戻り値の規約として「error が nil の時はポインタも非 nil」を徹底すると、毎回の nil チェックが不要になります。

3. nil interface の罠を避ける

type MyErr struct{}
 
func (*MyErr) Error() string { return "my error" }
 
func mayFail(cond bool) error {
    var e *MyErr
    if cond {
        e = &MyErr{}
    }
    return e // ← 型付き nil が interface にラップされ、!= nil が true になる
}

戻り値型が error の関数では失敗時のみ非 nil のポインタを返すように分岐を明示します(公式 FAQ(新しいタブで開く))。

func mayFail(cond bool) error {
    if cond {
        return &MyErr{}
    }
    return nil // 明示的に untyped nil を返す
}

4. map アクセスは存在確認を付ける

if v, ok := users[id]; ok {
    fmt.Println(v.Name)
} else {
    return fmt.Errorf("user %s not found", id)
}

ポインタ値が入る map では、未登録キーで返るゼロ値 (nil) を二項代入で必ず捕捉してから参照します。

この記事は役立ちましたか?