golang recover异常捕获容易踩的坑

golang recover捕获不到当前函数中的panic异常 运行下面的代码,会发现recover没有捕获到异常,原因是defer执行的函数在panic之后才被调用,也就是说defer根本就没有运行,因为myLog.Panic已经终止了函数调用 package main import( "fmt" "bytes" "log" ) func main(){ var buff bytes.Buffer // 自定义一个日志对象 // 默认的日志写入到buff中 myLog := log.New(&buff, "", log.LstdFlags) 阅读详情

1.error

Golang被诟病非常多的一点就是缺少强大方便的异常处理机制,大部分高级编程语言,比如Java、PHP、Python等都拥有一种try catch机制,这种异常捕获机制可以非常方便的处理程序运行中可能出现的各种意外情况。

严格来说,在Go里面,错误和异常是2种不同的类型,错误一般是指程序产生的逻辑错误,或者意料之中的意外情况,而且异常一般就是panic,比如角标越界、段错误。

对于错误,Golang采用了一种非常原始的手段,我们必须手动处理可能产生的每一个错误,一般会把错误返回给调用方,下面这种写法在Go里面十分常见:

package main
import (
	"errors"
	"fmt"
)

func main() {
	s, err := say()
	if err != nil {
		fmt.Printf("%s\n", err.Error())
	} else {
		fmt.Printf("%s\n", s)
	}
}

func say() (string, error) {
	// do something
	return "", errors.New("something error")
}
复制代码

这种写法最大的问题就是每一个error都需要判断处理,非常繁琐,如果使用try catch机制,我们就可以统一针对多个函数调用可能产生的错误做处理,节省一点代码和时间。不过咱们今天不是来讨论Go的异常错误处理机制的,这里只是简单说一下。

2.panic

一般错误都是显示的,程序明确返回的,而异常往往是隐示的,不可预测的,比如下面的代码:

package main

import "fmt"

func main() {
	fmt.Printf("%d\n", cal(1,2))
	fmt.Printf("%d\n", cal(5,2))
	fmt.Printf("%d\n", cal(5,0)) //panic: runtime error: integer divide by zero 
	fmt.Printf("%d\n", cal(9,5))
}

func cal(a, b int) int {
	return a / b
}
复制代码

在执行第三个计算的时候会发生一个panic,这种错误会导致程序退出,下面的代码的就无法执行了。当然你可以说这种错误理论上是可以预测的,我们只要在cal函数内部做好处理就行了。

然而实际开发中,会发生panic的地方可能特别多,而且不是这种一眼就能看出来的,在Web服务中,这样的panic会导致整个Web服务挂掉,特别危险。

3.recover

虽然没有try catch机制,Go其实有一种类似的recover机制,功能弱了点,用法很简单:

package main

import "fmt"

func main() {
	fmt.Printf("%d\n", cal(1, 2))
	fmt.Printf("%d\n", cal(5, 2))
	fmt.Printf("%d\n", cal(5, 0))
	fmt.Printf("%d\n", cal(9, 2))
}

func cal(a, b int) int {
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("%s\n", err)
		}
	}()
	return a / b
}
复制代码

首先,大家得理解defer的作用,简单说defer就类似于面向对象里面的析构函数,在这个函数终止的时候会执行,即使是panic导致的终止。

所以,在cal函数里面每次终止的时候都会检查有没有异常产生,如果产生了我们可以处理,比如说记录日志,这样程序还可以继续执行下去。

4.注意的坑

一般defer recover这种机制经常用在常驻进程的应用,比如Web服务,在Go里面,每一个Web请求都会分配一个goroutine去处理,在没有做任何处理的情况下,假如某一个请求发生了panic,就会导致整个服务挂掉,这是不可接受的,所以在Web应用里面必须使用recover保证即使某一个请求发生错误也不影响其它请求。

这里我使用一小段代码模拟一下:

package main

import (
	"fmt"
)

func main() {
	requests := []int{12, 2, 3, 41, 5, 6, 1, 12, 3, 4, 2, 31}
	for n := range requests {
		go run(n) //开启多个协程
	}

	for {
		select {}
	}
}

func run(num int) {
    //模拟请求错误
	if num%5 == 0 {
		panic("请求出错")
	}
	fmt.Printf("%d\n", num)
}
复制代码

上面这段代码无法完整执行下去,因为其中某一个协程必然会发生panic,从而导致整个应用挂掉,其它协程也停止执行。

解决方法和上面一样,我们只需要在run函数里面加入defer recover,整个程序就会非常健壮,即使发生panic,也会完整的执行下去。

func run(num int) {
	defer func() {
		if err := recover();err != nil {
			fmt.Printf("%s\n", err)
		}
	}()
	if num%5 == 0 {
		panic("请求出错")
	}
	fmt.Printf("%d\n", num)
}
复制代码

上面的代码只是演示,真正的坑是:如果你在run函数里面又启动了其它协程,这个协程发生的panic是无法被recover的,还是会导致整个进程挂掉,我们改造了一下上面的例子:

func run(num int) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("%s\n", err)
		}
	}()
	if num%5 == 0 {
		panic("请求出错")
	}
	go myPrint(num)
}

func myPrint(num int) {
	if num%4 == 0 {
		panic("请求又出错了")
	}
	fmt.Printf("%d\n", num)
}
复制代码

我在run函数里面又通过协程的方式调用了另一个函数,而这个函数也会发生panic,你会发现整个程序也挂了,即使run函数有recover也没有任何作用,这意味着我们还需要在myPrint函数里面加入recover。但是如果你不使用协程的方式调用myPrint函数,直接调用的话还是可以捕获recover的。

总结一下就是defer recover这种机制只是针对当前函数和以及直接调用的函数可能产生的panic,它无法处理其调用产生的其它协程的panic,这一点和try catch机制不一样。

理论上讲,所有使用协程的地方都必须做defer recover处理,这样才能保证你的应用万无一失,不过开发中可以根据实际情况而定,对于一些不可能出错的函数加了还影响性能。

Go的Web服务也是一样,默认的recover机制只能捕获一层,如果你在这个请求的处理中又使用了其它协程,那么必须非常慎重,毕竟只要发生一个panic,整个Web服务就会挂掉。

最后,总结一下,Go的异常处理机制虽然没有很多其它语言高效,但是基本上还是能满足需求,目前官方已经在着完善这一点,Go2可能会见到。

Go函数--panic和recover 0 简介 panic(宕机) 和 recover(恢复)是Go语言的两个内置函数,这两个内置函数用来处理Go的运行时错误(runtime errors)。panic 用来主动抛出异常,recover 用来捕获panic 抛出的异常。 1 基本概念 panic 和 recover的函数原型如下: panic(i interface{}) recover() interface{} ... 阅读详情

相关推荐

Golang领域recover的错误捕获策略

Golang以"简单、高效、可靠"著称,但再健壮的程序也会遇到意外:比如读取文件时文件被删除,调用接口时参数错误,甚至程序员手滑写出nil指针调用。这些意外如果不处理,会触发panic导致程序崩溃。本文将聚焦如何用recover安全捕获panic,涵盖基础用法、常见陷阱、实战场景和最佳实践,帮助你写出更健壮的Golang程序。本文将按照"故事引入→核心概念→原理拆解→实战案例→避坑指南"的逻辑展开:先用厨房起火的故事类比panic和recover;再拆解panic的传播机制与recover的工作原理;

AI Agent Harness Engineering 1051

Golang学习日志 ━━ 宕机恢复神器recover的一些要点

golang通过defer、panic和recover来实现其它语言中类似try...catch...的功能。 几个要点注意 recover 只能放到 defer 函数里面,不能放到子函数。实测直接 defer recover() 也不行。 参考:《golang recover() 的一个坑,记录一下。》 go的机制只能捕获一层,不同的gorutine里都要配recover 总结一下就是defer recover这种机制只是针对当前函数和以及直接调用的函数可能产生的panic,它无法处理其调用产生的其它协

暂时先用这个名字 964

基于RTL8370N的8口千兆无管理交换机硬件设计

无管理交换机是局域网边缘接入的核心基础设备,其本质是通过硬件状态机实现MAC地址学习、线速转发与自动协商,无需软件配置即可完成即插即用组网。原理上依赖高度集成的PHY+交换矩阵单芯片(如RTL8370N),结合确定性硬件逻辑替代MCU固件,保障低延迟、高可靠与零运维。技术价值体现在成本压缩、体积精简与部署极简化,广泛应用于家庭网络扩展、工业现场设备联网及嵌入式系统桥接等场景。本文详解一款基于RTL8370N的紧凑型8端口千兆无管理交换机,覆盖芯片选型依据、PHY接口设计、电源与散热优化等关键工程实践。

weixin_42327217的博客 399

一文搞懂Go语言错误处理【异常捕获、异常抛出】

介绍了go语言错误处理,以及创建错误对象,模拟异常的捕获。精简的代码实现硕大的功能。^_^在这里你会找到你想要的答案。

一个非常Cool的人 2099

用逻辑分析仪实测EM4095:125kHz RFID耳标解码的电压与脉宽玄学

本文通过逻辑分析仪实测EM4095芯片,深入解析125kHz RFID耳标解码中的电压与脉宽关联现象。揭示了供电电压对曼彻斯特编码脉宽的影响规律,并提供了一套可落地的调试方法论,包括信号链路解析、逻辑分析仪配置技巧及系统级稳定性提升方案,帮助开发者解决解码不稳定问题。

weixin_30629653的博客 328

在Ubuntu 20.04上,用EtherCAT Igh 1.6.2驱动高创BD3E伺服电机(附完整C代码)

本文详细介绍了在Ubuntu 20.04实时内核环境下,使用EtherCAT Igh 1.6.2主站驱动高创BD3E伺服电机的完整实现方案。从实时系统配置、伺服电机PDO映射到精确控制线程设计,提供了完整的C代码样例和实际项目中的调试技巧,帮助开发者实现工业自动化中的高精度运动控制。

weixin_30772105的博客 110

Go异常处理机制panic和recover

使用 panic 抛出异常后,函数执行将从调用 panic 的地方停止,如果函数内有 defer 调用,则执行 defer 后边的函数调用,如果 defer 调用的函数中没有捕获异常信息,这个异常会沿着函数调用栈往上传递,直到 main 函数仍然没有捕获异常,将会导致程序异常退出。因为panic发生的时候,panic函数后面的语句都不会执行了,所以recover函数不能放在panic语句后面执行,而要放在defer函数中执行。对于goroutine中的panic,协程外面的recover是无法恢复的;

techdashen的博客 685

Oracle 常用语法汇总

CREATE TABLE 表名(COMMENT ON COLUMN 注释;-- 创建一个学生表STUDENT_ID NUMBER(10) PRIMARY KEY, -- 学生ID,主键FIRST_NAME VARCHAR2(50) NOT NULL, -- 学生名字,不允许为空LAST_NAME VARCHAR2(50) NOT NULL, -- 学生姓氏,不允许为空EMAIL VARCHAR2(100) UNIQUE, -- 学生电子邮箱,唯一。

拽着尾巴的鱼儿的博客 2154

Go语言的错误和异常处理:error、panic和recover

在Go语言中,一般使用 error 这个接口类型表示错误,并且通常将 error 类型返回值放在返回值列表的末尾;error 接口类型是 Go 原生内置的类型,Go 在标准库中提供了两种构造错误值的方法: errors.New 和 fmt.Errorf,这两种方法只限于以字符串形式返回错误信息。Go 1.13 及后续版本中,尽量用errors.Is和errors.As函数。

码农兴哥的技术笔记 1988

绿盾注册机 使用手册

在很多涉及工程设计的单位(如建筑、模具、电路、广告等),电子图纸的应用极为普遍,而电子图纸的丢失、被盗对企业利益的影响是显而易见的,如果被竞争对手获取,甚至可能造成致命的打击。因此,对于这类企业,电子图纸的保密显得至关重要。绿盾信息安全管理软件充分考虑了电子图纸的各种可能传播途径,制定了针对性的解决方案,从而保证了电子图纸的安全。 我们总结了电子图纸的各种传播途径以及相应的对策,有如下几点:

996

Python白色飘雪(完整代码)

Python绘制白色飘雪动画的完整代码。

AIGC 3万+

golang特性之defer/recover异常捕获和处理机制

在上述代码中,我们使用了defer关键字来定义一个匿名函数,该函数中使用recover函数来捕获并处理当前的运行时异常。如果在someFunc函数中发生了panic异常,程序会进入到这个匿名函数中,并输出异常信息,然后程序会继续执行下去,而不是崩溃退出。通过使用defer关键字进行资源释放和清理操作,以及使用recover函数来捕获和处理运行时异常,程序员可以编写更可靠、更健壮的代码,从而提高程序的稳定性和可维护性。如果没有任何处理机制,这个异常会一直向上层函数传递,直到它遇到了主函数,导致整个程序崩溃。

SMILY12138的博客 659

21天教你学会PCIe专栏(14)--安全性考虑

1.1 定义安全性(Security):安全性是指保护系统免受未经授权的访问、攻击和破坏,确保数据的机密性、完整性和可用性。1.2 重要性数据保护:保护敏感数据,防止数据泄露和篡改。系统防护:防止恶意攻击,确保系统的稳定性和可靠性。合规性:满足行业标准和法律法规的要求,避免法律风险。用户信任:提高用户对系统的信任度,增强市场竞争力。通过今天的学习,你应该对PCIe安全性的重要性和常见威胁有了深入的了解,掌握了实施安全措施的方法和工具,以及安全开发的最佳实践。

xiaoheshang_123的博客 850

踩内存是什么意思啊_Go 语言踩坑记——panic 与 recover

题记Go 语言自发布以来,一直以高性能、高并发著称。因为标准库提供了 http 包,即使刚学不久的程序员,也能轻松写出 http 服务程序。不过,任何事情都有两面性。一门语言,有它值得骄傲的优点,也必定隐藏了不少坑。新手若不知道这些坑,很容易就会掉进坑里。《 Go 语言踩坑记》系列博文将以 Go 语言中的 panic 与 recover 开头,给大家介绍笔者踩过的各种坑,以及填坑方法。初...

weixin_39740419的博客 658

在树莓派4B上基于NCNN框架部署YOLOv8的实战教程

摘要:本文详细介绍了在树莓派4B上基于NCNN框架部署YOLOv8目标检测模型的完整流程。从PyTorch模型转换为NCNN格式,到树莓派环境配置(OpenCV和NCNN编译),再到C++代码实现与优化,涵盖模型加载、推理和绘图等核心功能。测试结果显示,树莓派4B上可实现约2 FPS的检测速度,Windows平台达6~7 FPS。文章还提供了量化模型、多线程优化等实用建议,并附常见问题解答,为边缘设备部署轻量化目标检测提供了可行方案。(149字)

m0_64661770的博客 595

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Golang 错误捕获 Panic 与 Recover

通过以上来简单熟悉Golang 与其他语言截然不同的错误处理形式,由于其他语言开发者经常将异常与控制结构混在一起,这会很容易使得代码变得混乱。开发者也很容易滥用异常,甚至一个小小的错误都抛出一个异常。这在Golang中不被允许,Go语言也就不支持传统的 try…catch…finally 这种异常,通过新的 defer panic recover 来进行错误处理。

猫轻王的博客 2541

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Go 语言踩坑记——panic 与 recover

题记 Go 语言自发布以来,一直以高性能、高并发著称。因为标准库提供了 http 包,即使刚学不久的程序员,也能轻松写出 http 服务程序。 不过,任何事情都有两面性。一门语言,有它值得骄傲的优点,也必定隐藏了不少坑。新手若不知道这些坑,很容易就会掉进坑里。《 Go 语言踩坑记》系列博文将以 Go 语言中的 panic 与 recover 开头,给大家介绍笔者踩过的各种坑,以及填坑方法。 初识 panic 和 recover panic panic 这个词,在英语中具有恐慌、恐慌的等意思。从字面意思理

爱生活,爱编程 1748

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

golang panic和recover 捕获异常

func panic(interface{})和func recover() interface{}是Golang中用于错误处理的两个函数。 panic的作用就是抛出一条错误信息,从它的参数类型可以看到它可以抛出任意类型的错误信息。在函数执行过程中的某处调用了panic,则立即抛出一个错误信息,同时函数的正常执行流程终止,但是该函数中panic之前定义的defer语句将被依次执行。之后该goro...

whatday的专栏 688

Go panic异常,recover()拦截异常(捕获异常)

demo.go(panic异常): package main import "fmt" func main() { fmt.Println("11111") panic("异常信息") // 手动抛出panic异常(运行时异常) fmt.Println("22222") // 异常之后的代码不会执行 } demo.go(recover()拦截异常,捕获异常): p...

houyanhua1的专栏 4240

【Go实战基础】Go 是如何捕获及处理异常的

目录 一、简介 二、数据结构 1、defer 2、panic 3、recover 三、菜鸟实战 1、创建 g007.go 2、编译和运行 3、运行结果 一、简介 Go 语言追求简洁优雅,不支持传统的 try - catch - finally 这种方式捕获和处理异常,Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得更加混乱。 在 Go 语言中,使用多值返回来返回错误,不要用异常代替错误,更不要用来控制流程。 在遇到真正的异常的情况下(比如除数为0了),才使用

菜鸟实战的博客 2820

go 异常捕获处理 panic defer recover

简言 在其他语言里,宕机往往以异常的形式存在,底层抛出异常,上层逻辑通过 try/catch 机制捕获异常,没有被捕获的严重异常会导致宕机 go语言追求简洁,优雅,Go语言不支持传统的 try…catch…finally 这种异常 Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱 Go语言,可以使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别...

papaya的博客 2070

golang eof 错误_Golang异常处理panic、recover机制详解

(给Go开发大全加星标)来源:XITEHIPhttps://www.jianshu.com/p/c7248f4804c7【导读】golang 的错误恢复常用到panic、recover。本文通过汇编信息和具体例子,对panic、recover原理进行了详细的底层分析环境:go version go1.12.5 linux/amd64panicgolang中的异常总共分为4中:编译器捕获的...

weixin_39688687的博客 4500

recover 没有捕获异常_说说Golang异常捕获

01Golang panic recover详解Go 语言中的 panic 的作用就是抛出一条错误信息,从它的参数类型可以看到它可以抛出任意类型的错误信息。在函数执行过程中的某处调用了 panic,则立即抛出一个错误信息,同时函数的正常执行流程终止,但是该函数中 panic 之前定义的 defer 语句将被依次执行。之后该 goroutine 立即停止执行。recover() 用于将 p...

weixin_34201593的博客 517

golang之recover

这包括关闭文件、释放资源或执行其他清理操作,以确保程序的状态正确恢复,并且不会留下未处理的副作用。时,最好记录相关信息,并进行适当的报告。函数,我们可以实现程序的优雅恢复和错误处理,从而提高代码的可维护性和稳定性。中恢复,我们可以防止程序因错误而崩溃,而是采取适当的措施处理错误。函数时,需要谨慎使用,并遵循最佳实践,以确保代码的可读性和稳定性。是Go语言中的异常机制,当程序发生不可恢复的错误时,会引发一个。

all_about_WZY的博客 6872

【go】异常处理panic和recover

【go】简单讲解go语言中的异常处理机制----panic和recover

2501_90745824的博客 984

recover 没有捕获异常_golang捕获异常

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的...

weixin_39955781的博客 246
上一篇: golang全局变量的坑-尽量别用全局变量
下一篇: 谈谈NAT:什么?全球IP和私有IP是什么鬼?
phpduang
博客等级 码龄10年 9粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值