Bootstrap

【Golang学习之旅】Go 语言错误处理(error 接口、panic、recover)

前言

✅ 适合人群:Golang 开发者 | 后端开发工程师 | 并发编程初学者
✅ 文章亮点:深入解析 error、panic、recover + 代码示例 + 实战场景
✅ 目标:掌握 Go 语言错误处理机制,编写健壮、高质量的 Go 代码!

1. 为什么要学习 Go 语言错误处理?

在 Go 语言中,错误处理是一项 非常重要的技能,因为 Go 没有异常机制(不像 Java、Python 的try-catch)。而是通过返回错误对象进行错误处理,同时提供了panicrevover处理严重错误。

📌 常见错误处理场景:
✅ 文件操作:文件不存在、权限不足
✅ 网络请求:请求超时、连接失败
✅ 数据库操作:SQL 语法错误、连接池耗尽
✅ 用户输入:非法输入、数据校验失败

🔹 Go 语言错误处理方式:
1️⃣error接口:返回错误对象,让调用者处理
2️⃣panic:程序遇到无法恢复的错误时触发
3️⃣recover:拦截panic,防止程序崩溃

2. Go语言的error接口

2.1 什么是error接口?

error是Go语言内置的一个接口,用于表示错误信息:

type error interface {
	Error() string
}

🔹 Go 语言错误处理的基本原则:
✅ 普通错误使用 error 处理(推荐方式)
✅ 严重错误使用 panic处理
✅ 程序应尽可能优雅地恢复

2.2 创建 & 返回错误

方式1:使用errors.New创建错误

package main

func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, errors.New("除数不能为 0")
	}
	return a / b, nil
}

func main(){
	result, err := divide(10, 0)
	  if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("结果:", result)
    }
}

📌 运行结果:

错误: 除数不能为 0

🔹 解析:

  1. errors.New("错误信息")创建一个错误对象
  2. return 0, errors New(...)返回错误
  3. 调用方法必须检查error,否则可能导致程序崩溃!

方式2:使用fmt.Errorf格式化错误

package main

import (
    "fmt"
)

func openFile(filename string) error {
	return fmt.Errorf("文件 %s 打开失败", filename)
}

func main(){
	err := openFile("data.txt")
	if err != nil {
        fmt.Println("错误:", err)
    }
}

📌 输出:

错误: 文件 data.txt 打开失败

🔹fmt.Errorf可以格式化错误信息,推荐使用!

方式 3:自定义错误类型


package main

import (
    "fmt"
)

// 自定义错误类型
type MyError struct {
	Code int
	Msg string
}

func (e *MyError) Error() string {
	return fmt.Sprintf("错误码 %d:%s", e.Code, e.Msg)
}

func checkValue(val int) error {
	if val < 0 {
		return &MyError{Code: 400, Msg:"值不能为负数"}
	}
	return nil
}

func main() {
	err := checkValue(-1)
	if err != nil {
        fmt.Println("发生错误:", err)
    }
}

📌 输出:

发生错误: 错误码 400: 值不能为负数

3. Go 语言的 panic & recover

3.1 什么是 panic?

panic用于表示程序发生严重错误,无法继续执行,通常用于不可恢复的错误,如:
✅ 数组越界
✅ 空指针引用
✅ 文件未找到

3.2 使用 panic 终止程序

package main

import "fmt"

func divide(a, b int) int {
    if b == 0 {
        panic("除数不能为 0") // 触发 panic
    }
    return a / b
}

func main() {
    fmt.Println(divide(10, 2)) // 正常运行
    fmt.Println(divide(5, 0))  // 发生 panic
}

📌 运行结果:

5
panic: 除数不能为 0

🔹 一旦 panic 触发,程序会立即崩溃,并打印调用栈信息!

3.3 使用 recover 拦截 panic

recover() 可用于捕获 panic,让程序 优雅地恢复

package main

import "fmt"

func safeDivide(a, b int) {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("捕获错误:", err)
        }
    }()
    fmt.Println("结果:", a/b)
}

func main() {
    safeDivide(10, 2) // 正常执行
    safeDivide(5, 0)  // 触发 panic,但不会崩溃
}

📌 运行结果:

结果: 5
捕获错误: 除数不能为 0

🔹 为什么使用 defer recover()
✅ 拦截 panic,避免程序崩溃
✅ 可以记录日志,方便排查错误

4. Go 语言错误处理最佳实践

1️⃣ 普通错误使用 error 处理,避免panic
2️⃣ panic 只用于不可恢复的错误(如严重异常)
3️⃣ 使用 recover 处理 panic,避免整个程序崩溃
4️⃣ 错误信息应清晰,方便调试
5️⃣ 提供详细错误日志,避免“error: something went wrong”

🎯 总结 & 进阶学习方向

📌 本篇文章深入解析了 Go 语言的错误处理机制,包括error接口、panicrecover,帮助你编写更健壮的 Go 代码。
📌 进阶学习:Go 语言日志管理(log、zap)、Go 语言 Web 开发(Gin 框架)
📌 学习资源:Go 官方文档

;