错误定义
Go 的错误处理主要围绕以下机制展开:
error接口:标准的错误表示- 显式返回值:通过函数的返回值返回错误
- 自定义错误:可以通过标准库或自定义的方式创建错误
panic和recover:处理不可恢复的严重错误
Error 接口
Go 标准库定义了一个 error 接口,表示一个错误的抽象
go
type error interface {
Error() string
}任何实现 error 接口中方法的类型都可以作为错误使用
go
// 通过自定义属性定义一个“运行时异常”
type RuntimeException string
func (e RuntimeException) Error() string {
return string(e)
}Error 包
标准库提供了一个 error 包可以快速创建错误
go
import (
"errors"
"fmt"
)
func main() {
err := errors.New("这是一个错误")
fmt.Println(err) // 输出:这是一个错误
}处理
错误通常作为函数的返回值返回
方法使用
一般错误内容都是在函数的最后一个返回值上
go
func divide(a, b int) (int, error) {
if b == 0 {
return 0, RuntimeException("除数不能为零")
}
return a / b, nil
}自定义错误
go
package main
import (
"fmt"
)
// 定义 ResponseResult 错误
type ResponseResult struct {
Code int
Msg string
}
func (e ResponseResult) Error() string {
return fmt.Sprintf("%d: %s", e.Code, e.Msg)
}
func main() {
// 测试请求
result, err := request()
if err != nil {
fmt.Println(err) // 500: 服务器错误
} else {
fmt.Println(result)
}
}
// 模拟请求
func request() (string, error) {
// 模拟请求失败
if true {
return "请求失败", ResponseResult{Code: 500, Msg: "服务器错误"}
}
return "请求成功", nil
}errors.Is / errors.As
自 1.13 起,errors 包引入了 errors.Is 和 errors.As 用于处理错误链
errors.Is:检查某个错误是否是特定错误或由该错误包装而成
go
// 定义 ResponseResult 错误
type ResponseResult struct {
Code int
Msg string
}
func (e ResponseResult) Error() string {
return fmt.Sprintf("%d: %s", e.Code, e.Msg)
}
// 预先定义一个服务器错误类型
var ServerError = ResponseResult{Code: 500, Msg: "服务器错误"}
func main() {
// 测试请求
result, err := request()
if errors.Is(err, ServerError) {
fmt.Println(err)
} else {
fmt.Println(result)
}
}
// 模拟请求
func request() (string, error) {
// 模拟请求失败
if true {
return "请求失败", ResponseResult{Code: 500, Msg: "服务器错误"}
// 事实上也可以直接返回 ServerError
}
return "请求成功", nil
}errors.As:将错误转换为特定类型以便进一步处理(第二个参数一定要取址)
go
func main() {
// 测试请求
_, err := request()
var respResult ResponseResult
// 检查是否为服务器错误类型,如果是的话把错误信息赋值给respResult并返回true
if errors.As(err, &respResult) {
fmt.Println(respResult)
}
}panic / recover
panic 用于处理不可恢复的错误,recover 用于从 panic 中恢复
panic:
- 导致程序崩溃并输出堆栈信息
- 常用于程序无法继续运行的情况
recover:捕获 panic,避免程序崩溃
go
func safeFunction() {
defer func() {
r := recover()
if r != nil {
fmt.Println("从 panic 恢复:", r)
}
}()
panic("发生错误")
}
func main() {
fmt.Println("开始程序...")
safeFunction()
fmt.Println("程序继续执行")
}
/*-------输出结果-------
开始程序...
从 panic 恢复: 发生错误
程序继续执行
*/