Golang 异常处理

本文介绍了Go语言中不同于其他语言的异常处理方式,强调了错误作为主要处理手段,以及panic和defer/recover函数在处理程序中断和恢复中的作用。通过实例展示了如何使用这些机制来控制程序流程。
摘要由CSDN通过智能技术生成

前言

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()")
}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值