1. 数组/切片索引越界(Index Out of Range)
这是Go中最常见的panic原因。当访问数组/切片的索引超出其长度范围时,运行时会直接触发panic。
避坑建议:访问前检查索引是否满足 0 ≤ idx < len(s),或使用循环遍历(如for range)避免手动指定索引。
2. 空指针解引用(Nil Pointer Dereference)
声明指针变量但未初始化(默认值为nil),却尝试访问其指向的结构体字段/方法,是高频panic场景。
避坑建议:使用指针前先初始化(如u = &User{Name: "Tom"}),或通过if u != nil做非空检查。
3. 类型断言失败(非ok模式)
类型断言时如果不使用ok模式,且断言的类型与实际类型不匹配,会直接触发panic。
避坑建议:始终使用ok模式做类型断言:
4. 通道操作不当
• 重复关闭通道;
• 向已关闭的通道发送数据;
这两种操作都会触发panic(从已关闭通道接收数据不会panic,会返回零值+false)。
避坑建议:确保通道只关闭一次(如通过逻辑标记控制),发送数据前检查通道状态。
5. 除以零(Division by Zero)
数值运算中除数为0,是数学上的非法操作,Go运行时会直接panic。
避坑建议:运算前检查除数是否为0,避免非法运算。
6. sync包的误用(互斥锁重复解锁/未加锁解锁)
sync.Mutex/sync.RWMutex的解锁操作必须与加锁成对出现,未加锁解锁、重复解锁都会panic。
避坑建议:加锁后立即用defer mu.Unlock()确保解锁操作只执行一次,避免手动控制出错。
7. 调用nil函数
函数类型的变量如果是nil,调用它会触发panic。
避坑建议:调用函数前检查if f != nil,或确保函数变量被正确赋值。
8. 修改nil切片的元素
nil切片的长度和容量均为0,直接修改其元素会panic(但appendnil切片是安全的,会自动分配内存)。
避坑建议:修改切片元素前先初始化(如s = make([]int, 1)),或通过append初始化。
总结
1. Go中panic的核心根源是非法内存访问(索引越界、空指针解引用等)和资源/运算操作不合法(重复关通道、除以零等);
2. 规避panic的关键是:操作前做合法性检查(如非空、索引范围),使用安全模式(如类型断言的ok模式),确保资源操作成对唯一;
3. 即使无法完全避免panic,也可通过recover()在defer中捕获panic。