错误处理
在 Go 中,错误处理被设计为显式的。它鼓励开发者明确地检查错误,而不是依赖异常。基本思想是可能遇到错误的函数需返回结果和错误两个值,该函数的调用方负责检查和处理返回的错误。
返回错误
可能遇到错误的函数将一个类型为 error
的值作为最后一个返回类型。
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}
你可以使用 errors.New
创建一个新错误,或者使用 fmt.Errorf
创建更复杂的错误消息。
if err := someFunction(); err != nil {
return fmt.Errorf("error in someFunction: %w", err)
}
处理错误
始终显式地检查错误。你可以使用 if
语句检查错误。
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result)
}
通过从函数返回错误将错误传播到调用堆栈上。每个层次可以决定如何处理或包装错误。
func compute() error {
result, err := divide(10, 0)
if err != nil {
return fmt.Errorf("error in compute: %w", err)
}
// 继续处理
// ...
}
Panic
panic
函数可用于引发运行时 panic。一般用于暴露无法有效处置的错误,甚至中断程序。
func example() {
panic("serious error that cannot be handled here")
}
延迟
defer
语句可用于确保在程序执行的最后阶段执行函数调用,通常用于清理目的。这对于处理 panic 和释放资源很有用。
file, err := os.Open("example.txt")
if err != nil {
return err
}
defer file.Close()
// ...
恢复
recover
函数用于重新获得对 panic 的控制。
func example() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
// 引发 panic 的代码
panic("something went wrong")
}
自定义错误
可以通过实现 error
接口来创建自定义错误类型。
type MyError struct {
Msg string
}
func (e *MyError) Error() string {
return e.Msg
}
这允许你为错误提供更多的上下文和信息。
err := &MyError{Msg: "This is a custom error"}
总之,Go 代码偏向于显式错误处理,而不是抛异常。这可以使代码更可预测,也更可读。
代码挑战
编写一个名为
ReverseString
的函数,它以字符串作为输入,并返回其反转值。
记得处理输入字符串为空的情况,并为此情况返回自定义错误。
Loading...
> 此处输出代码运行结果