Golang 异常处理
前言
Go语言中,"异常"的概念与其他语言如Java或Python中的不太相同。Go没有提供传统意义上的try-catch
机制来捕获异常。相反,Go使用错误作为其错误处理的主要方式
感觉很麻烦,到处都要处理…,没有传统的try-catch
好用
常见异常的处理
- 向上一级抛,示例
func SomeFunction() (int, error) {
// ... function logic ...
// When an error occurs
if somethingWentWrong {
return 0, errors.New("something went wrong")
}
// No error occurred
return result, nil
}
func main() {
result, err := SomeFunction()
if err != nil {
// handle the error
fmt.Println("Error occurred:", err)
} else {
// no error, use the result
fmt.Println("Success:", result)
}
}
- 中断程序
一般用于初始化
package main
import (
"fmt"
"os"
)
func init() {
// 读取不到配置文件
_, err := os.ReadFile("config.yaml")
if err != nil {
panic(err.Error()) // panic 函数会立即停止当前函数的执行
// 或者使用 log.Fatalln("配置文件读取失败")
}
}
func main() {
fmt.Println("Hello, World!")
}
这个例子中,panic函数会立即停止当前函数的执行,然后逐层向上返回,直到被程序的顶层调用者捕获,这时程序通常会崩溃,抛出panic:panic: open config.yaml: The system cannot find the file specified.
或者使用 log.Fatalln()
,它里面会执行os.Exit(1)
,程序也会立马终止,但可以自定义提示信息
- 恢复程序
在第2步的基础上,可以通过defer
语句配合recover
函数来捕获和处理这种类型的错误
这也是用到的比较多的
recover
是一个内置函数,用于"捕获"或"恢复"一个panic
。recover
只有在defer
语句中调用时才有效。如果在没有发生panic
的情况下调用recover
,或者不在defer
语句中调用recover
,它将不会有任何效果,并返回nil
当代码执行到panic
时,正常的函数执行流程会被中断,然后Go运行时会开始逐层向上回退(unwind)调用栈,运行每一层的defer
语句。如果在这个过程中某个defer
语句中调用了recover
,recover
会捕获到panic
的值,并且阻止panic
继续向上传播。这样,程序就有机会从错误中恢复,继续执行
看个例子:
package main
import "fmt"
func mayPanic() {
panic("a problem")
}
func main() {
defer func() {
if r := recover(); r != nil {
// 处理错误
fmt.Println("Recovered. Error:\n", r)
// 处理完错误,然后下面执行正常逻辑代码
// 正常代码
}
}()
mayPanic()
// 这行代码只有在recover成功捕获panic后才会运行
fmt.Println("After mayPanic()")
}
mayPanic函数调用panic,此时main函数中的defer语句会被执行。在这个defer语句中,recover函数被调用并捕获了panic的值。因此,程序从panic中恢复过来,而不是终止执行。然后程序会继续执行main函数中defer之后的代码。如果没有recover捕获panic,程序将会终止,并打印出panic信息和堆栈跟踪
处理错误时,可能希望查看具体是哪里执行出错,可以使用
fmt.Println(string(debug.Stack()))
它会打印详细的调用栈信息,可以具体到出错的行
进一步,我们单独弄个函数来处理
package main
import "fmt"
func mayPanic() {
panic("a problem")
}
func dealWithPanic() {
defer func() {
if r := recover(); r != nil {
// 处理错误
fmt.Println("Recovered. Error:\n", r)
}
}()
mayPanic()
}
func main() {
dealWithPanic()
// 正常要处理的代码
fmt.Println("After mayPanic()")
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!