The Error Explained
The nil pointer dereference is Go's most common runtime error. When you see this message, your program tried to access memory through a nil pointer:
``` panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x4a1b4f]
goroutine 1 [running]: main.(*UserService).GetEmail(...) /app/service.go:45 ```
This error means you have a pointer variable that is nil, and you tried to dereference it (access the value it points to).
Why It Happens
In Go, a pointer is nil when it hasn't been initialized or explicitly set to nil. When you try to access a field or call a method on a nil pointer, Go crashes.
Scenario 1: Uninitialized Struct Pointer
```go type Config struct { Port int Host string }
func main() { var cfg *Config // cfg is nil here fmt.Println(cfg.Port) // PANIC! } ```
Fix: Initialize the pointer
func main() {
cfg := &Config{Port: 8080, Host: "localhost"}
fmt.Println(cfg.Port) // Works: 8080
}Scenario 2: Function Returns Nil
```go type Database struct { connection string }
func Connect(dsn string) *Database { if dsn == "" { return nil // Returns nil for empty DSN } return &Database{connection: dsn} }
func main() { db := Connect("") // db is nil fmt.Println(db.connection) // PANIC! } ```
Fix: Check for nil before using
func main() {
db := Connect("")
if db == nil {
log.Fatal("Failed to connect to database")
}
fmt.Println(db.connection)
}Scenario 3: Map with Nil Pointer Values
```go type User struct { Name string Email *string // pointer field }
func main() { users := map[int]*User{ 1: {Name: "Alice", Email: strPtr("alice@example.com")}, 2: {Name: "Bob"}, // Email is nil }
for id, user := range users { fmt.Printf("User %d email: %s\n", id, *user.Email) // PANIC for Bob! } }
func strPtr(s string) *string { return &s } ```
Fix: Check pointer fields before dereferencing
for id, user := range users {
email := "not set"
if user.Email != nil {
email = *user.Email
}
fmt.Printf("User %d email: %s\n", id, email)
}Scenario 4: Interface Nil Gotcha
This is a subtle case that trips many developers:
```go type Printer interface { Print() }
type Document struct{}
func (d *Document) Print() { fmt.Println("Printing...") }
func getPrinter() Printer { var d *Document // d is nil return d // Returns nil *Document as interface }
func main() { p := getPrinter() if p == nil { fmt.Println("Printer is nil") return } p.Print() // PANIC! p is NOT nil, but contains nil pointer } ```
The interface value has two parts: a type and a value. Here, p has type *Document and value nil. So p == nil is false!
Fix: Check the concrete value
```go func isNil(i interface{}) bool { if i == nil { return true } v := reflect.ValueOf(i) switch v.Kind() { case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Chan, reflect.Func, reflect.Interface: return v.IsNil() } return false }
func main() { p := getPrinter() if isNil(p) { fmt.Println("Printer is nil") return } p.Print() } ```
Debugging Technique
Add a nil check helper for development:
```go func must[T any](v *T, msg string) *T { if v == nil { panic(fmt.Sprintf("nil pointer: %s", msg)) } return v }
// Usage config := must(loadConfig(), "config cannot be nil") fmt.Println(config.Port) ```
Verification Commands
```bash # Run with panic stack traces enabled GOTRACEBACK=all go run main.go
# Use delve debugger to inspect state dlv debug main.go (dlv) break main.go:42 (dlv) continue (dlv) print myPointer ```
Prevention with Static Analysis
Install and run nilaway for automatic detection:
go install go.uber.org/nilaway/cmd/nilaway@latest
nilaway ./...Example output:
/app/service.go:45:3: error: Potential nil panic detected. Method `GetEmail` called on a result of `GetUser` that may be nil.