Go错误处理与panic/recover
Go错误处理使用返回值方式,panic/recover用于异常情况。
error接口
错误定义
Go
// error是接口类型
type error interface {
Error() string
}
// 创建错误
err := errors.New("出错了")
err := fmt.Errorf("错误: %d", code)
错误检查
Go
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("除数不能为0")
}
return a / b, nil
}
result, err := divide(10, 0)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println("结果:", result)
panic异常
触发panic
Go
func checkAge(age int) {
if age < 0 {
panic("年龄不能为负数")
}
}
checkAge(-1) // panic,程序崩溃
panic用于不可恢复的错误,如配置缺失、致命错误。
panic特性
Go
func main() {
fmt.Println("开始")
panic("崩溃")
fmt.Println("不会执行") // panic后代码不执行
}
// 输出:
// 开始
// panic: 崩溃
recover恢复
捕获panic
Go
func safeProcess() {
defer func() {
if r := recover(); r != nil {
fmt.Println("捕获panic:", r)
}
}()
panic("出错")
}
safeProcess()
fmt.Println("程序继续")
recover必须在defer中调用才能捕获panic。
recover工作原理
Go
// recover返回panic的值
func recoverDemo() {
defer func() {
if r := recover(); r != nil {
fmt.Println("恢复:", r)
// 可以处理panic
}
}()
panic("panic值")
}
// 输出:恢复: panic值
panic/recover流程
Go
┌─────────────────────────────────────┐
│ 函数执行 │
│ │
│ panic触发 │
│ ↓ │
│ 执行defer │
│ ↓ │
│ defer中调用recover │
│ ↓ │
│ recover捕获panic值 │
│ ↓ │
│ 程序继续执行(若recover成功) │
└─────────────────────────────────────┘
错误处理最佳实践
普通错误返回error
Go
func readFile(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return data, nil
}
// 调用者检查错误
data, err := readFile("data.txt")
if err != nil {
// 处理错误
}
panic用于不可恢复错误
Go
func mustConfig() {
config := loadConfig()
if config == nil {
panic("配置缺失,程序无法启动")
}
}
recover用于服务恢复
Go
func serveHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
w.WriteHeader(500)
fmt.Println("服务恢复:", r)
}
}()
processRequest(r)
}
error与panic对比
| 特性 | error | panic |
|---|---|---|
| 用途 | 可预期错误 | 不可恢复错误 |
| 处理方式 | 返回值检查 | recover捕获 |
| 程序继续 | 检查后继续 | recover后继续 |
| 适用场景 | 业务错误 | 致命错误 |
| 性能影响 | 无 | 有 |
自定义错误类型
text
type ValidationError struct {
Field string
Msg string
}
func (e ValidationError) Error() string {
return e.Field + ": " + e.Msg
}
func validate(name string) error {
if name == "" {
return ValidationError{Field: "name", Msg: "不能为空"}
}
return nil
}
要点总结
- error是接口,实现Error()方法
- 普通错误返回error,调用者检查
- panic用于不可恢复的致命错误
- recover必须在defer中调用
- recover返回panic的值
- panic后程序崩溃,recover后继续
- 不要滥用panic,普通错误用error
- 服务可用recover保证可用性
📝 发现内容有误?点击此处直接编辑