Files
wehub-resource-sync bb5c75ce05
Component Security Validation / Security Audit (push) Has been cancelled
Deploy to Cloudflare Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:58 +08:00

8.8 KiB

Go Error Patterns

Common Go errors with diagnosis and solutions.

Nil Pointer Errors

panic: runtime error: invalid memory address or nil pointer dereference

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation]

Causes:

  1. Calling method on nil pointer
  2. Accessing field of nil struct
  3. Dereferencing nil pointer

Solutions:

// Check for nil before use
if user != nil {
    fmt.Println(user.Name)
}

// Return early on nil
func processUser(user *User) error {
    if user == nil {
        return errors.New("user is nil")
    }
    // proceed
}

// Use zero values where appropriate
type Config struct {
    Timeout time.Duration
}

func (c *Config) GetTimeout() time.Duration {
    if c == nil {
        return 30 * time.Second // default
    }
    return c.Timeout
}

Slice/Array Errors

panic: runtime error: index out of range

panic: runtime error: index out of range [5] with length 3

Causes:

  1. Accessing index beyond slice length
  2. Empty slice access
  3. Off-by-one error

Solutions:

// Check length first
if len(items) > index {
    item := items[index]
}

// Safe first/last element
func first(items []string) (string, bool) {
    if len(items) == 0 {
        return "", false
    }
    return items[0], true
}

// Use range for iteration
for i, item := range items {
    // safe access
}

panic: runtime error: slice bounds out of range

panic: runtime error: slice bounds out of range [:5] with length 3

Solutions:

// Validate slice bounds
func safeSlice(s []int, start, end int) []int {
    if start < 0 {
        start = 0
    }
    if end > len(s) {
        end = len(s)
    }
    if start > end {
        return nil
    }
    return s[start:end]
}

Map Errors

panic: assignment to entry in nil map

panic: assignment to entry in nil map

Causes:

  1. Writing to uninitialized map
  2. Map declared but not made

Solutions:

// Wrong
var m map[string]int
m["key"] = 1  // panic!

// Correct - use make
m := make(map[string]int)
m["key"] = 1

// Or initialize with literal
m := map[string]int{}
m["key"] = 1

// In structs, initialize in constructor
type Cache struct {
    data map[string]string
}

func NewCache() *Cache {
    return &Cache{
        data: make(map[string]string),
    }
}

Map access returns zero value

value := m["nonexistent"]  // Returns zero value, not error

Solutions:

// Check if key exists
value, ok := m["key"]
if !ok {
    // key doesn't exist
}

// Or use default
func getOrDefault(m map[string]int, key string, def int) int {
    if v, ok := m[key]; ok {
        return v
    }
    return def
}

Channel Errors

fatal error: all goroutines are asleep - deadlock!

fatal error: all goroutines are asleep - deadlock!

Causes:

  1. Channel send/receive with no corresponding operation
  2. Unbuffered channel blocking
  3. Waiting on channel that's never written to

Solutions:

// Wrong - unbuffered channel blocks
ch := make(chan int)
ch <- 1  // blocks forever, no receiver

// Correct - use goroutine
ch := make(chan int)
go func() {
    ch <- 1
}()
value := <-ch

// Or use buffered channel
ch := make(chan int, 1)
ch <- 1  // doesn't block
value := <-ch

// Always close channels when done sending
go func() {
    defer close(ch)
    for _, item := range items {
        ch <- item
    }
}()

panic: send on closed channel

panic: send on closed channel

Solutions:

// Only sender should close channel
// Use sync.Once for safe closing
var once sync.Once
closeCh := func() {
    once.Do(func() {
        close(ch)
    })
}

// Or use context for cancellation
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go func() {
    for {
        select {
        case <-ctx.Done():
            return
        case ch <- value:
        }
    }
}()

Interface Errors

panic: interface conversion: X is nil, not Y

panic: interface conversion: interface {} is nil, not string

Solutions:

// Use type assertion with ok
value, ok := i.(string)
if !ok {
    // handle non-string or nil
}

// Use type switch
switch v := i.(type) {
case string:
    fmt.Println("string:", v)
case int:
    fmt.Println("int:", v)
case nil:
    fmt.Println("nil")
default:
    fmt.Println("unknown type")
}

panic: interface conversion: X is Y, not Z

panic: interface conversion: interface {} is int, not string

Same solution - always use type assertion with ok check.


Concurrency Errors

fatal error: concurrent map writes

fatal error: concurrent map writes

Causes:

  1. Multiple goroutines writing to same map
  2. No synchronization

Solutions:

// Option 1: Use sync.Mutex
type SafeMap struct {
    mu sync.RWMutex
    m  map[string]int
}

func (s *SafeMap) Set(key string, value int) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.m[key] = value
}

func (s *SafeMap) Get(key string) (int, bool) {
    s.mu.RLock()
    defer s.mu.RUnlock()
    v, ok := s.m[key]
    return v, ok
}

// Option 2: Use sync.Map
var m sync.Map
m.Store("key", 1)
value, ok := m.Load("key")

data race detected

WARNING: DATA RACE
Write by goroutine X:
  ...
Previous read by goroutine Y:
  ...

Solutions:

// Use mutex for shared state
var (
    mu    sync.Mutex
    count int
)

func increment() {
    mu.Lock()
    count++
    mu.Unlock()
}

// Or use atomic operations
var count int64

func increment() {
    atomic.AddInt64(&count, 1)
}

// Run with race detector
// go run -race main.go
// go test -race ./...

Import/Module Errors

cannot find package

cannot find package "github.com/user/repo" in any of:
    /usr/local/go/src/github.com/user/repo (from $GOROOT)
    /home/user/go/src/github.com/user/repo (from $GOPATH)

Solutions:

# Initialize go modules
go mod init myproject

# Download dependencies
go mod tidy

# Or get specific package
go get github.com/user/repo

module declares its path as X but was required as Y

module declares its path as: github.com/old/path
        but was required as: github.com/new/path

Solutions:

# Update go.mod with replace directive
# go.mod
replace github.com/old/path => github.com/new/path v1.0.0

# Or update import paths in code

Error Handling Patterns

Wrapping Errors (Go 1.13+)

// Wrap with context
if err != nil {
    return fmt.Errorf("failed to process user %d: %w", userID, err)
}

// Unwrap to check original error
if errors.Is(err, sql.ErrNoRows) {
    // handle not found
}

// Get specific error type
var pathErr *os.PathError
if errors.As(err, &pathErr) {
    fmt.Println("Path:", pathErr.Path)
}

Custom Errors

// Sentinel errors
var ErrNotFound = errors.New("not found")

// Custom error type
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

// Check with errors.As
var valErr *ValidationError
if errors.As(err, &valErr) {
    fmt.Printf("Validation failed on %s\n", valErr.Field)
}

Build Errors

undefined: X

./main.go:10:2: undefined: someFunction

Causes:

  1. Function/variable not defined
  2. Wrong package imported
  3. Unexported name (lowercase)

Solutions:

// Check export - must be uppercase
func PublicFunction() {}  // Exported
func privateFunction() {} // Not exported

// Check import
import "mypackage"
mypackage.PublicFunction()

imported and not used

./main.go:4:2: "fmt" imported and not used

Solutions:

// Remove unused import
// Or use blank identifier if needed for side effects
import _ "database/sql/driver"

// Use goimports to auto-fix
// goimports -w .

declared and not used

./main.go:10:2: x declared and not used

Solutions:

// Use the variable or remove it
// Use blank identifier if intentionally unused
_ = someFunction()

// For error checking
result, _ := riskyFunction()  // Intentionally ignore error (not recommended)

Quick Reference Table

Error Category Quick Fix
nil pointer dereference Nil Check for nil before use
index out of range Slice Check len() first
assignment to nil map Map Use make(map[K]V)
deadlock Channel Ensure send/receive pairs match
send on closed channel Channel Only sender closes
interface conversion nil Interface Use type assertion with ok
concurrent map writes Concurrency Use sync.Mutex or sync.Map
data race Concurrency Add synchronization, use -race
cannot find package Module Run go mod tidy
undefined Build Check export (uppercase)