Go语言基础-错误处理

Go 语言错误处理机制

错误类型

Go 的内置错误类型通过 error 接口提供了一种简单而有效的错误处理机制。

error 接口

在 Go 中,error 是一个内置接口,定义如下:

type error interface {
    Error() string
}

error 接口只有一个方法 Error(),返回一个描述错误的字符串。这使得任何实现了 Error() 方法的类型都可以被视为错误。

创建自定义错误

开发者可以通过实现 error 接口来自定义错误类型。例如:

type MyError struct {
    Message string
    Code    int
}

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

在这个例子中,MyError 是一个自定义错误类型,包含错误消息和错误代码。实现 Error() 方法后,MyError 类型可以作为错误使用。

使用内置错误类型

Go 标准库提供了一些内置的错误类型,例如:

fmt.Errorf

用于创建带有格式化字符串的错误。

err := fmt.Errorf("failed to open file: %s", filename)

errors.New

用于创建一个简单的错误。

err := errors.New("an error occurred")

错误包装

从 Go 1.13 开始,可以使用 fmt.Errorf 来包装错误,以便提供更多上下文信息。通过 %w 语法,可以将原始错误作为新错误的一部分:

originalErr := errors.New("original error")
wrappedErr := fmt.Errorf("an additional context: %w", originalErr)

检查错误类型

可以使用 errors.Iserrors.As 来检查错误的类型,方便处理不同类型的错误:

if errors.Is(err, specificErr) {
    // 处理特定类型的错误
}

返回错误

返回错误的基本用法如下:

func doSomething() error {
    // 发生错误时返回
    return fmt.Errorf("an error occurred")
}

检查错误

检查返回错误的基本示例:

if err := doSomething(); err != nil {
    fmt.Println("Error:", err)
}

panic 与 recover

panic() 是 Go 语言中的一个内置函数,用于触发恐慌状态。它主要用于处理程序中不可恢复的错误,导致程序停止执行并开始回溯。

panic() 被调用时,Go 会执行以下步骤:

  1. 停止当前函数的执行:当前函数会立即停止执行,所有未完成的操作(如 defer 语句)会被执行。
  2. 逐层回溯:程序会逐层回溯,执行每层调用栈中的 defer 语句,直到找到一个可以捕获 panicrecover()
  3. 程序崩溃:如果没有任何 recover() 捕获这个 panic,程序将打印错误信息并退出。

recover() 是 Go 语言中用于处理恐慌状态的内置函数。它的主要作用是捕获因 panic 触发的异常,以便程序能够继续执行,而不是完全崩溃。

recover() 只能在 defer 声明的函数中使用。它的功能是捕获 panic 产生的值,返回该值,如果没有发生 panic,则返回 nil

示例

package main

import (
    "fmt"
)

func mayPanic() {
    panic("something went wrong!")
}

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    
    mayPanic() // 触发 panic
    fmt.Println("This will not be printed")
}

func main() {
    safeFunction()
    fmt.Println("Program continues after recovery.")
}

输出结果:

Recovered from panic: something went wrong!
Program continues after recovery.

在上面的示例中,mayPanic 函数触发了一个 panic,但通过 recover() 捕获并处理了这个 panic,程序得以继续执行。

设计模式:返回错误 vs使用 panic

  • 返回错误:这种模式适合于可以预期的错误,如文件未找到、网络请求失败等。调用者可以通过检查错误值来决定下一步的处理逻辑。

    func readFile(filename string) error {
        // 模拟读取文件错误
        return fmt.Errorf("file not found: %s", filename)
    }
    
  • 使用 panic:适合处理严重的程序错误,例如逻辑错误、配置错误等。这类错误通常表明代码中存在缺陷,无法继续执行。

    func main() {
        if err := performCriticalOperation(); err != nil {
            panic(err) // 不可恢复的错误
        }
    }
    
posted @ 2024-10-05 00:24  ffff5  阅读(5)  评论(0编辑  收藏  举报