症状
出现 panic: runtime error: invalid memory address or nil pointer dereference;服务退出或 HTTP 处理器返回 500 与堆栈;只有在依赖返回错误或查找未命中时出现。
诊断
从堆栈最内层应用帧开始阅读:
go test ./... 2>&1 | grep -B5 -A10 'nil pointer'
最顶部的应用帧指出确切的解引用位置,记录文件与行号。用 go test -race -run TestName -v ./... 复现并检查并发访问。然后检查该位置附近的错误返回与 map 查找:
grep -n 'err\|, ok :=\|return nil' path/to/file.go
被忽略的错误或缺失的 ok 检查通常解释了 nil 如何到达解引用点。
根因
Go 在解引用 nil 指针时 panic。值变成 nil 的原因包括忽略错误、查找未命中、构造函数返回 nil,或接口中持有 nil 具体值却与 nil 比较不相等。
修复
user, err := store.FindUser(ctx, id)
if err != nil {
return "", fmt.Errorf("find user %s: %w", id, err)
}
if user == nil {
return "", ErrUserNotFound
}
return user.Email, nil
检查错误后再使用结果;map 与类型断言使用双返回值;在 nil 时提前返回;使用前初始化指针。如果 nil 是合法值,应显式保护解引用并定义降级行为。
验证
为产生 nil 的输入添加回归测试并运行 go test -race;确认处理器返回定义好的错误而不是 panic;日志包含操作与标识符,而不只是“nil pointer”。
风险提示
recover() 可以把 panic 变成 500 并隐藏根因,只应在进程或请求边界配合日志与指标使用,不能作为主要的 nil 检查手段。