Go 处理错误异常

2024-05-15 10:04
文章标签 go 异常 处理错误

本文主要是介绍Go 处理错误异常,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在Go语言中错误和异常是两个完全不同的概念,错误指的是可能出现问题的地方出现了问题,而异常指的是不该出现问题的地方出现了问题

从Go语言的机制上讲错误和异常就是error 和panic的区别

  • 错误(Error):程序中预期会发生的错误,预料之中

  • 异常(Panic):不该出现问题的地方出现了问题,预料之外

  • 错误是业务的一部分,而异常不是,异常是我们不想要的

自定义错误(Error) 

在自定义错误中,只需要定义结构体来实现Error()方法即可 

package mainimport ("fmt""gopkg.in/errgo.v2/errors"
)// MyError 创建一个错误结构体
type MyError struct {msg  stringcode interror
}// type error interface { Error() string }实现错误接口
func (e *MyError) Error() string {// 返回Error stringreturn fmt.Sprintf("错误信息:%s,错误代码:%d,c错误值%s\n", e.msg, e.code, e.error)}
func (e *MyError) print() bool {return true}func test(i int) (int, error) {if i != 0 {// 使用自定义的Error进行返回return i, &MyError{msg:   "输入的值不等于0",code:  500,error: errors.New("3333333"),}}// 正常结果return i, nil
}func main() {i, err := test(1)if err != nil {// 使用断言判断err类型my_err, ok := err.(*MyError)if ok {if my_err.print() {// 处理err的子逻辑}}fmt.Println(my_err.msg, my_err.code, my_err.error)}fmt.Println(i)
}

异常(Panic)

Go语言中没有try...catch语句,如果需要处理异常则需要使用panic抛出异常,recover来接收处理异常 

在使用panic和recover来处理异常的时候必须要结合defer延迟函数来完成

package mainimport ("fmt"
)func testPanic(i int) {// 出去函数的时候处理这里面可能发生的panic// recover func recover() any 返回panic传递的值// panic   func panic(v any)defer func() {if err := recover(); err != nil {fmt.Println("捕获到的panic异常---------->", err)}}()if i > 0 {panic("这是运行过程中出现异常的------panic")}
}
func main() {testPanic(1)
}

处理Panic后再次出现Panic怎么办

在 Go 语言中,deferrecover 是用于异常处理的两个关键字。recover 用于捕获 panic 产生的异常,防止程序因为 panic 而崩溃,并且可以恢复程序的执行流程。defer 允许你在函数退出时执行代码,无论函数是正常结束还是因为调用了 panic 或者遇到了其他异常。

当你在一个使用了 recoverdefer 语句中再次引发 panic,recover 可以捕获到这个 panic,但是这将导致程序进入一个异常的递归状态,因为 recover 已经处于处理 panic 的状态。在实际应用中,你通常不应该在已经调用了 recoverdefer 语句中再次引发 panic,因为这会使得错误处理变得复杂且难以追踪。 

package mainimport ("fmt"
)func mayPanic() {defer func() {if r := recover(); r != nil {fmt.Println("从恐慌---1中恢复过来:", r)// 错误地再次引发 panicpanic("恐慌---2")}}()panic("恐慌---1")
}func main() {defer func() {if r := recover(); r != nil {fmt.Println("从恐慌中恢复过来:", r)}}()mayPanic()fmt.Println("如果mayPanic没有恢复,将不会打印此信息,因为出现恐慌1的过程中再次出现恐慌")/*mayPanic 函数中的 defer 语句尝试捕获一个 panic,然后错误地再次引发 panic。然而,由于 recover 已经在处理一个 panic,再次引发 panic 将不会被捕获,程序将终止*/
}

为了避免这种情况,你应该避免在 recover 内部再次引发 panic。如果你需要处理错误或 panic 产生的结果,你可以直接返回错误或进行其他类型的处理,而不是再次 panic。

正确的错误处理方式可能包括记录日志、清理资源、向调用者返回错误等。在实际应用中,你应该仔细设计错误处理逻辑,确保程序的稳定性和可维护性。

处理多个 panic

处理多个 panic 的情况通常涉及到多个 defer 语句 

在 Go 语言中,处理多个 panic 的情况通常涉及到多个 defer 语句。每个 defer 语句都是独立的,并且按照它们出现的逆序(即最后一个 defer 先执行)来执行。这意味着你可以在不同的 defer 块中使用 recover 来捕获并处理 panic

如果一个函数中有多个地方可能引发 panic,并且你希望对每个 panic 进行特定的处理,你可以在每个潜在的 panic 点后面放置一个 defer 块,并在其中使用 recover

package mainimport ("fmt"
)func mayPanic1(str string) {defer func() {if r := recover(); r != nil {fmt.Printf("从恐慌中恢复 %s\n", r)}}()// 模拟可能发生 panic 的代码//出现Panic后是不会继续执行Panic所在的函数继续执行下去的panic(str)
}
func mayPanic2(str string) {defer func() {if r := recover(); r != nil {fmt.Printf("从恐慌中恢复 %s\n", r)}}()defer func() {if r := recover(); r != nil {fmt.Printf("(defer recover的顺序是按照它们出现的逆序执行的)从恐慌中恢复 %s\n", r)}}()// 模拟可能发生 panic 的代码//出现Panic后是不会继续执行Panic所在的函数继续执行下去的panic(str)
}
func mayPanic3(str string) {// 模拟可能发生 panic 的代码//出现Panic后是不会继续执行Panic所在的函数继续执行下去的panic(str)
}
func main() {defer func() {if r := recover(); r != nil {fmt.Printf("从恐慌中恢复过来: %v\n", r)}}()mayPanic1("恐慌--A")fmt.Println("由于恐慌--A已恢复,将打印此行")mayPanic2("恐慌--B")fmt.Println("由于恐慌--B已恢复,将打印此行")mayPanic3("恐慌--C")fmt.Println("出现Panic后是不会继续执行Panic所在的函数继续执行下去的,此行将不会打印")
}

这篇关于Go 处理错误异常的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991523

相关文章

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO