Golang 异常处理

前言

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()")
}
golang 中,异常被称作 panic。当程序出现异常情况时,会导致程序崩溃并且打印出错误信息。为了避免程序崩溃,我们可以使用 recover 函数来捕获 panic 并进行处理。 下面是一个简单的例子: ```go func main() { defer func() { if err := recover(); err != nil { fmt.Println("Recovered from", err) } }() panic("something went wrong") } ``` 在上面的例子中,我们使用 defer 关键字和一个匿名函数来调用 recover 函数。当 panic 函数被调用时,程序将会崩溃并且进入到 defer 函数中。在 defer 函数中,我们调用了 recover 函数来捕获 panic,并且打印出错误信息。注意:在 defer 函数中使用 recover 函数是必须的,否则程序仍然会崩溃。 除了使用 defer 函数和 recover 函数外,我们还可以使用 error 类型来处理异常。例如: ```go func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil } func main() { result, err := divide(10, 0) if err != nil { fmt.Println("Error:", err) return } fmt.Println(result) } ``` 在上面的例子中,我们定义了一个函数 divide 来计算两个浮点数的除法。如果除数为 0,函数将会返回一个 error 类型的值,并且包含错误信息。在调用 divide 函数时,我们使用了一个 if 语句来检查返回的错误,如果错误不为空,则打印出错误信息并且退出程序。否则,我们会打印出计算结果。 总之,在 golang 中,我们可以使用 defer 函数和 recover 函数来处理异常,也可以使用 error 类型来返回错误信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值