Skip to content

错误定义

Go 的错误处理主要围绕以下机制展开:

  1. error 接口:标准的错误表示
  2. 显式返回值:通过函数的返回值返回错误
  3. 自定义错误:可以通过标准库或自定义的方式创建错误
  4. panicrecover:处理不可恢复的严重错误

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.Iserrors.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 恢复: 发生错误
程序继续执行
*/