Golang 异常处理

发布时间:2024年01月09日

前言

Go语言中,"异常"的概念与其他语言如Java或Python中的不太相同。Go没有提供传统意义上的try-catch机制来捕获异常。相反,Go使用错误作为其错误处理的主要方式
感觉很麻烦,到处都要处理…,没有传统的try-catch好用

常见异常的处理

  1. 向上一级抛,示例
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)
    }
}
  1. 中断程序
    一般用于初始化
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),程序也会立马终止,但可以自定义提示信息

  1. 恢复程序
    在第2步的基础上,可以通过defer语句配合recover函数来捕获和处理这种类型的错误
    这也是用到的比较多的

recover 是一个内置函数,用于"捕获"或"恢复"一个panicrecover只有在defer语句中调用时才有效。如果在没有发生panic的情况下调用recover,或者不在defer语句中调用recover,它将不会有任何效果,并返回nil

当代码执行到panic时,正常的函数执行流程会被中断,然后Go运行时会开始逐层向上回退(unwind)调用栈,运行每一层的defer语句。如果在这个过程中某个defer语句中调用了recoverrecover会捕获到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()")
}
文章来源:https://blog.csdn.net/e5pool/article/details/135470451
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。