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.