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所在的函数继续执行下去的,此行将不会打印")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/837935.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

17.多线程

多线程 程序、进程、线程的概念 程序:是指令和数据的有序集合,是一个静态的概念。比如,在电脑中,打开某个软件,就是启动程序。 进程:是执行程序的一次执行过程,是一个动态的概念,…

c# 实现每个整数分钟执行一次的定时任务

StartAsync 方法中,计算了下一个整数分钟的时间,然后使用 System.Threading.Timer 类创建定时器,并将首次触发时间设为该时间。在 InsertDB2Async 方法中,我们定义了要执行的操作,然后使用 await Task.Delay(1000) 模拟…

mongo副本集本地部署

介绍 前言: mongodb 因为高性能、高可用性、支持分片等特性,作为非关系型数据库被大家广泛使用。其高可用性主要是体现在 mongodb 的副本集上面(可以简单理解为一主多从的集群),本篇文章主要从副本集介绍、docker搭建…

blender渲染时导致cpu高负载的可能因素

Blender 在进行渲染时(尤其是在使用 Cycles 渲染引擎时)通常会导致 CPU 高负载的原因主要有以下几个: 渲染计算:Blender 的 Cycles 渲染引擎是一种基于光线追踪的渲染引擎,它通过追踪光线在场景中的传播来生成图像。这…

基于SSM的“口腔护理网站”的设计与实现(源码+数据库+文档)

基于SSM的“口腔护理网站”的设计与实现(源码数据库文档) 开发语言:Java 数据库:MySQL 技术:SSM 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 首页 用户注册页面 医生信息查看模块 口腔护理预约模块 后台首页面…

分享如何通过定时任务调用lighthouse前端测试脚本+在持续集成测试中调用lighthouse前端测试脚本

最近写了个小工具来优化lighthouse在实际工作中的使用,具体实现了:通过定时任务调用前端测试脚本在持续集成测试中调用前端测试脚本。由于在公司中已经应用,所以就不能提供源码了,这里简单说一下实现思路,希望可以帮助…

Java 循环结构 - for, while 及 do...while

Java 循环结构 - for, while 及 do…while 顺序结构的程序语句只能被执行一次。 如果您想要同样的操作执行多次,就需要使用循环结构。 Java中有三种主要的循环结构: while 循环 do…while 循环 for 循环 在 Java5 中引入了一种主要用于数组的增强型 f…

前端面试题日常练-day04 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末。 1. 下列哪个 CSS 单位可以根据用户的首选字体大小进行调整&#xff1f; A) pxB) emC) remD) vw2. HTML5 中的<video>元素用于什么&#xff1f; A) 播放音频文件B) 嵌入外部网页内容C) 显示图…

Debezium日常分享系列之:Debezium 2.7.0.Alpha2发布

Debezium日常分享系列之&#xff1a;Debezium 2.7.0.Alpha2发布 新功能和改进1.Oracle ROW_ID 包含在更改事件中2.带有 JDBC 接收器的 PostreSQL 数组3.Oracle 使用自定义模式名称刷新表4.使用 JWT/seed 进行 NATS 身份验证5.Oracle 大量表查询过滤器 新功能和改进 1.Oracle R…

OUC图书馆电脑开启无线网络,连接手机热点,解决联网但无法访问网络的问题

OUC图书馆电脑连手机热点 前言手动脚本&#xff08;暂未测试&#xff09;注意 前言 【中国海洋大学】OUC图书馆电脑默认只能有线连校园网&#xff0c;这让没有校园网的人很是头疼&#xff08;手机流量太多了&#xff0c;根本用不完&#xff0c;需要大流量卡的可以私信我&#…

在Android设备丢失数据后恢复数据的4个方法

了解 Android 媒体存储 媒体存储是下载、查看、播放和流式传输视频文件、音频文件、图像和其他媒体文件时所需的过程。此服务无法从手机桌面访问&#xff0c;因此您需要按照以下步骤通过安卓手机访问此系统服务。 步骤1&#xff1a;导航到手机设置&#xff0c;然后转到应用程…

Flink中基于Chandy-Lamport算法的分布式快照实现详解

Apache Flink利用了一种基于Chandy-Lamport分布式快照算法的变体——异步屏障快照&#xff08;Asynchronous Barrier Snapshotting, ABS&#xff09;来实现其强大的容错机制。Chandy-Lamport算法最初由K.M. Chandy和Leslie Lamport于1985年提出&#xff0c;是一种用于分布式系统…

linux shell脚本追踪与调试命令之sh

linux shell脚本在执行之前,大家就怕出问题,该如何调试呢?我们有没有办法不需要通过直接执行该脚本就判断是否有问题呢?当然有,那就是sh命令。 1.sh用法 sh [参数] shell.sh sh命令参数 参数说明-n不需要执行脚本,仅查询语法问题-v在执行脚本前,先将脚本的内容输出到…

初识鸿蒙之ArkTS基础

前言 学习一种应用程序开发&#xff0c;需要从这种程序的开发语言开始&#xff0c;比如说Android开发从入门到放弃&#xff0c;肯定是从Java基础或者是Kotlin语言基础开始学习的&#xff0c;IOS程序开发也肯定是从object-c开始学习的。鸿蒙软件开发也不例外&#xff0c;如果做…

【scikit-learn003】K近邻ML模型实战及经验总结(更新中)

1.一直以来想写下基于scikit-learn训练AI算法的系列文章&#xff0c;作为较火的机器学习框架&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架K近邻&#xff08;K-Nearest Neighb…

机器学习(五) ----------集成学习(1)(集成学习思想+随机森林算法)

目录 1 核心思想 2 集成学习思想分类 2.1 Bagging&#xff08;Bootstrap aggregating&#xff09; 2.1.1 基本思想 2.1.2 特点 2.1.3 优点&#xff1a; 2.1.4 缺点&#xff1a; 2.2 Boosting&#xff08;Boosting Method&#xff09; 2.2.1 基本思想 2.2.2 特点 2.2.…

Vue3+TS实现将html或富文本编辑器转为Word并下载

说明&#xff1a;我用的富文本编辑器是wangEditor&#xff1a; wangEditor官网 安装 yarn add wangeditor/editor # 或者 npm install wangeditor/editor --save yarn add wangeditor/editor-for-vuenext # 或者 npm install wangeditor/editor-for-vuenext --save yarn add …

Git版本控制工具的原理及应用详解(二)

本系列文章简介&#xff1a; 随着软件开发的复杂性不断增加&#xff0c;版本控制成为了开发团队中不可或缺的工具之一。在过去的几十年里&#xff0c;版本控制工具经历了各种发展和演变&#xff0c;其中Git无疑是目前最受欢迎和广泛应用的版本控制工具之一。 Git的出现为开发者…

金万维动态域名小助手怎么用?

金万维动态域名小助手是一个域名检测工具&#xff0c;使用此工具可以进行检测域名解析是否正确、清除DNS缓存、修改DNS服务器地址及寻找在线客服&#xff08;仅支持付费用户&#xff09;等操作。对不懂网络的用户是一个很好的检测域名的工具&#xff0c;下面我就讲解一下金万维…

Java聚合项目打包运行笔记

聚合项目创建 略 聚合项目打包配置 父工程 pom文件添加 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>…