}

Fix 'nil pointer dereference' Panic in Go (2026)

runtime error: invalid memory address or nil pointer dereference

A nil pointer dereference panic means your program tried to read or write through a pointer that holds no address (nil). The immediate fix is to add a nil check before dereferencing: if p == nil { return }.

The Full Panic Output

goroutine 1 [running]:
main.main()
        /home/user/project/main.go:14 +0x18
exit status 2
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47d8a4]

The key fields: - addr=0x0 — the program tried to access memory address zero, which is nil - The goroutine stack trace shows the exact file and line - The line number in main.go:14 is where the dereference happened


What nil Means in Go

In Go, nil is the zero value for pointers, interfaces, slices, maps, channels, and functions. It means "this variable points to nothing."

Type Zero value Panics when
*T (pointer) nil You dereference it (*p or p.Field)
interface{} nil You call a method on it
map[K]V nil You write to it (m[k] = v)
chan T nil You send or receive on it
func(...) nil You call it
[]T (slice) nil Safe to read length/range; panics on index if empty

Note: A nil slice is safe to range over and len(nil slice) returns 0. It only panics if you index into it with an out-of-range index. A nil map is also safe to read — m[key] returns the zero value — but panics on write.


Cause 1: Uninitialized Pointer

The simplest case — declaring a pointer variable without initializing it.

Broken code:

package main

import "fmt"

type User struct {
    Name string
    Age  int
}

func main() {
    var u *User          // u is nil
    fmt.Println(u.Name)  // panic: nil pointer dereference
}

Fixed code — initialize with a struct literal:

func main() {
    u := &User{Name: "Alice", Age: 30}   // u points to a real User
    fmt.Println(u.Name)                   // "Alice"
}

Fixed code — initialize with new:

func main() {
    u := new(User)       // allocates a zeroed User, u is *User pointing to it
    u.Name = "Alice"
    fmt.Println(u.Name)  // "Alice"
}

Cause 2: Forgetting to Check Error Returns

Functions that return (*T, error) return nil for the pointer when an error occurs. Using the pointer without checking the error is the most common source of nil panics in real code.

Broken code:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func getUser(db *sql.DB, id int) (*User, error) {
    row := db.QueryRow("SELECT name FROM users WHERE id=$1", id)
    var u User
    err := row.Scan(&u.Name)
    if err != nil {
        return nil, err   // returns nil pointer on error
    }
    return &u, nil
}

func main() {
    db, _ := sql.Open("postgres", "...")
    user, _ := getUser(db, 999)   // user is nil if id=999 not found
    fmt.Println(user.Name)         // panic: nil pointer dereference
}

Fixed code:

func main() {
    db, err := sql.Open("postgres", "...")
    if err != nil {
        log.Fatal(err)
    }
    user, err := getUser(db, 999)
    if err != nil {
        log.Printf("user not found: %v", err)
        return
    }
    fmt.Println(user.Name)  // safe: user is not nil here
}

The rule: Always check err != nil before using any pointer that came from a function that could fail.


Cause 3: Nil Interface Value

An interface value is nil when both its type and value components are nil. Calling a method on a nil interface panics.

Broken code:

package main

import "fmt"

type Animal interface {
    Speak() string
}

func makeSound(a Animal) {
    fmt.Println(a.Speak())   // panics if a is nil
}

func main() {
    var a Animal   // nil interface
    makeSound(a)   // panic: nil pointer dereference (or: interface method called on nil value)
}

Fixed code:

func makeSound(a Animal) {
    if a == nil {
        fmt.Println("(silence)")
        return
    }
    fmt.Println(a.Speak())
}

Subtle gotcha — a non-nil interface holding a nil pointer:

type Dog struct{}
func (d *Dog) Speak() string { return "woof" }

var d *Dog     // nil pointer
var a Animal = d   // a is NOT nil — the interface has a type (*Dog) but nil value

// a == nil is FALSE here!
// a.Speak() will panic because the method receiver is nil

This is one of the trickiest Go gotchas. The fix is to not assign a nil concrete pointer to an interface, or to handle it in the method:

func (d *Dog) Speak() string {
    if d == nil {
        return "(silent dog)"
    }
    return "woof"
}

Cause 4: Writing to a Nil Map

Broken code:

package main

func main() {
    var counts map[string]int     // nil map
    counts["hello"]++             // panic: assignment to entry in nil map
}

Fixed code:

func main() {
    counts := make(map[string]int)   // initialized map
    counts["hello"]++                // safe
}

Reading from a nil map is safe — it returns the zero value:

var m map[string]int
fmt.Println(m["key"])   // prints 0, no panic

Cause 5: Nil Pointer in Struct Fields

When you embed a pointer type inside a struct and forget to initialize it, accessing the embedded fields panics.

Broken code:

type Config struct {
    Database *DatabaseConfig
}

type DatabaseConfig struct {
    Host string
    Port int
}

func main() {
    cfg := Config{}             // Database field is nil *DatabaseConfig
    fmt.Println(cfg.Database.Host)   // panic: nil pointer dereference
}

Fixed code:

func main() {
    cfg := Config{
        Database: &DatabaseConfig{
            Host: "localhost",
            Port: 5432,
        },
    }
    fmt.Println(cfg.Database.Host)   // "localhost"
}

Or add a defensive check:

func main() {
    cfg := Config{}
    if cfg.Database != nil {
        fmt.Println(cfg.Database.Host)
    }
}

Reading a Stack Trace

When a nil pointer panic occurs, Go prints the full goroutine stack. Here is how to read it:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x48d3c2]

goroutine 1 [running]:
main.getUser(...)
        /home/user/app/users.go:23 +0x89     ← line 23 in users.go panicked
main.main()
        /home/user/app/main.go:14 +0x44      ← called from line 14 in main.go
exit status 2

Read from the top of the goroutine block downward: the topmost frame is where the panic happened. Work down to understand the call chain. The +0xNN offsets are byte offsets into the function — ignore them; focus on file and line numbers.


Nil-Safe Patterns

Pattern 1: Guard at the top of every method that can receive nil

func (u *User) DisplayName() string {
    if u == nil {
        return "anonymous"
    }
    return u.Name
}

Pattern 2: Return zero values instead of nil pointers when possible

// Instead of returning *Config (can be nil)
func loadConfig() Config {    // returns value type, never nil
    return Config{Host: "localhost", Port: 8080}
}

Pattern 3: Use the ok-pattern with maps

val, ok := myMap[key]
if !ok {
    // key not present, val is zero value
}

Pattern 4: Initialize maps and slices in struct constructors

type Store struct {
    cache map[string]int
    items []string
}

func NewStore() *Store {
    return &Store{
        cache: make(map[string]int),
        items: []string{},
    }
}

FAQ

Q: How can I tell from the panic message which variable is nil?

A: The stack trace shows the line number. Go to that line in your editor. Look for any dereference operations: *p, p.Field, p.Method(), p[key] (where p is a pointer, interface, map, or function). Add a fmt.Printf or use a debugger (dlv) to print the value before the panic line to confirm which one is nil.

Q: Is it ever OK to have a nil pointer in Go?

A: Yes. Go code often uses nil as a valid sentinel (e.g., var err error = nil means success). Pointer types commonly use nil to mean "not present". The problem is only when you dereference nil — reading or writing through it. Keep nil pointers and check them before use.

Q: My function returns (*T, error). Should I always check error before using *T?

A: Yes, always. The Go convention is that when err != nil, all other return values should be considered invalid (they are typically their zero values, including nil for pointers). Never use T when err != nil.


Related Articles