Go 语言错误处理机制
错误类型
Go 的内置错误类型通过 error
接口提供了一种简单而有效的错误处理机制。
error 接口
在 Go 中,error
是一个内置接口,定义如下:
type error interface {Error() string
}
error
接口只有一个方法 Error()
,返回一个描述错误的字符串。这使得任何实现了 Error()
方法的类型都可以被视为错误。
创建自定义错误
开发者可以通过实现 error
接口来自定义错误类型。例如:
type MyError struct {Message stringCode 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.Is
和 errors.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 会执行以下步骤:
- 停止当前函数的执行:当前函数会立即停止执行,所有未完成的操作(如
defer
语句)会被执行。 - 逐层回溯:程序会逐层回溯,执行每层调用栈中的
defer
语句,直到找到一个可以捕获panic
的recover()
。 - 程序崩溃:如果没有任何
recover()
捕获这个panic
,程序将打印错误信息并退出。
recover()
是 Go 语言中用于处理恐慌状态的内置函数。它的主要作用是捕获因 panic
触发的异常,以便程序能够继续执行,而不是完全崩溃。
recover()
只能在 defer
声明的函数中使用。它的功能是捕获 panic
产生的值,返回该值,如果没有发生 panic
,则返回 nil
。
示例
package mainimport ("fmt"
)func mayPanic() {panic("something went wrong!")
}func safeFunction() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()mayPanic() // 触发 panicfmt.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) // 不可恢复的错误} }