go中 panicrecoverdefer机制

 go的defer机制-CSDN博客 

常见panic场景

  • 数组或切片越界,例如 s := make([]int, 3); fmt.Println(s[5]) 会引发 panic: runtime error: index out of range
  • 空指针调用,例如 var p *Person; fmt.Println(p.Name) 会引发 panic: runtime error: invalid memory address or nil pointer dereference
  • 过早关闭 HTTP 响应体,例如 resp, err := http.Get(url); defer resp.Body.Close(); if err != nil { return err } 会引发 panic: runtime error: invalid memory address or nil pointer dereference,因为如果 http.Get 出错,resp 可能是 nil
  • 除以零,例如 x := 0; y := 1 / x 会引发 panic: runtime error: integer divide by zero
  • 向已经关闭的 channel 发送或接收消息,例如 ch := make(chan int); close(ch); ch <- 1 会引发 panic: send on closed channel
  • 重复关闭 channel,例如 ch := make(chan int); close(ch); close(ch) 会引发 panic: close of closed channel
  • 关闭未初始化的 channel,例如 var ch chan int; close(ch) 会引发 panic: close of nil channel
  • 未初始化的 map,例如 var m map[string]int; m["key"] = 1 会引发 panic: assignment to entry in nil map

recover常用的场景

  • panic 只会触发当前 Goroutine 的 defer
  • recover 只有在 defer 中调用才会生效;
package mainimport "fmt"func main() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()fmt.Println("Before panic")panic("Something went wrong")fmt.Println("After panic") // This line will not be executed
}运行结果Before panic
Recovered from panic: Something went wrong

defer,recover,panic,goroutine之间有什么联系呢

recover的作用域,recover在什么时候才会起作用

recover什么时候有效

recover未在defer内使用,是不会起任何作用

func main() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}fmt.Println("Before panic")panic("Something went wrong")fmt.Println("After panic") // This line will not be executed
}结果Before panic
panic: Something went wronggoroutine 1 [running]:
main.main()/Users/alan/GolandProjects/design-patterns/main.go:11 +0x78

recover必须搭配defer使用

recover在defer内使用才会起作用

package mainimport "fmt"func main() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()fmt.Println("Before panic")panic("Something went wrong")fmt.Println("After panic") // This line will not be executed
}运行结果Before panic
Recovered from panic: Something went wrong

recove的作用域

recover在父协程

举个例子,一般使用chan的时候都是要在发送测关闭chan,我们在接受者通过控制超时

让函数提前退出,子协程一秒钟后退出


func main() {test()time.Sleep(time.Second * 10)
}
func test() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()var ch = make(chan int)go get_data(ch)ctx, cancel := context.WithTimeout(context.Background(), time.Second)defer cancel()defer close(ch)select {case <-ch:returncase <-ctx.Done():return}
}
func get_data(ch chan int) {time.Sleep(time.Second * 2)ch <- 1
}

结果

我们发现没有recover住panic,子协程在test方法调用退出后,发生了panic,导致整个程序panic挂掉

recover,panic同子协程

相同的例子我们,我们在引起panic的协程内进行recover,结果函数正常recover后程序正常退出

func main() {test()time.Sleep(time.Second * 10)fmt.Println("时间到了 主函数也溜了")
}
func test() {defer func() {fmt.Println("test:我先溜了")}()var ch = make(chan int)go get_data(ch)ctx, cancel := context.WithTimeout(context.Background(), time.Second)defer cancel()defer close(ch)select {case <-ch:returncase <-ctx.Done():return}
}
func get_data(ch chan int) {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()time.Sleep(time.Second * 2)ch <- 1
}

结果

正确使用close关闭chan

recover在同级函数作用域下起效

引用

Go 语言踩坑记——panic 与 recover | 小米信息部技术团队

Go 语言 panic 和 recover 的原理 | Go 语言设计与实现

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

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

相关文章

Android Init Language

Android Init Language 安卓初始化语言&#xff0c;是一种用于配置和管理 Android 系统服务的专用脚本语言。主要用于编写 .rc 文件&#xff08;比如我们熟知的init.rc文件&#xff09;&#xff0c;这些文件在系统启动时由 init 进程读取和执行&#xff0c;从而设置和启动系统服…

Mako 模板语言

Mako 模板语言 Mako的哲学:Python is great scripting language ,don’t reinvent the wheel, your template can handle it !, api非常简单, ####入门 Template类是创建模板和渲染模板的核心类 from mako.template import Template mytemplate Template("hello world&…

网络通信tcp

一、udp案例 二、基于tcp: tcp //c/s tcp 客户端: 1.建立连接 socket bind connect 2.通信过程 read write close tcp服务器: 1.建立连接 socket bind listen accept 2.通信过程 read write close connect函数 int connect(int sockfd, con…

Git克隆仓库太大导致拉不下来的解决方法 fatal: fetch-pack: invalid index-pack output

一般这种问题是因为某个文件/某个文件夹/某些文件夹过大导致整个项目超过1G了导致的 试过其他教程里的设置depth为1,也改过git的postBuffer,都不管用 最后还是靠克隆指定文件夹这种方式成功把项目拉下来 1. Git Bash 输入命令 git clone --filterblob:none --sparse 项目路径…

探索Unity3D URP后处理在UI控件Image上的应用

探索Unity3D URP后处理在UI控件Image上的应用 前言初识URP配置后处理效果将后处理应用于UI控件方法一&#xff1a;自定义Shader方法二&#xff1a;RenderTexture的使用 实践操作步骤一&#xff1a;创建RenderTexture步骤二&#xff1a;UI渲染至RenderTexture步骤三&#xff1a;…

视频如何转gif?分享这几款软件!

在这个快节奏、高创意的互联网时代&#xff0c;动图&#xff08;GIF&#xff09;以其独特的魅力成为了社交媒体、聊天软件中的宠儿。它们不仅能瞬间抓住眼球&#xff0c;还能让信息传递更加生动有趣。然而&#xff0c;你是否曾为如何将精彩瞬间从视频中精准截取并转换成GIF而苦…

富士变频器主板EP-3611E-C EP-3611E-C-Z2

富士变频器主板EP-3611E-C EP-3611E-C-Z2 ‌富士变频器主板EP-3611E-C EP-3611E-C-Z2‌是富士电机株式会社研发、生产、销售的世界知名变频器品牌之一的一部分。富士变频器&#xff0c;全称为“富士交流变频调速器”&#xff0c;主要用于三相异步交流电机&#xff0c;通过改变…

​北斗终端:无人驾驶领域的导航新星

一、北斗终端在无人驾驶领域的应用 北斗终端&#xff0c;作为我国自主研发的北斗卫星导航系统的重要组成部分&#xff0c;其在无人驾驶领域中的应用正逐步显现其独特魅力。北斗系统的高精度、高可靠性和良好的抗干扰性能&#xff0c;为无人驾驶车辆提供了精确的定位和导航服务…

go实现一个简单的微服务

一、前言 我们知道要实现一个微服务需要实现前端页面、后端处理程序、和底层的数据库。 1.1 前端 负责收集用户的信息&#xff0c;或者说接受用户的请求。例如&#xff0c;用户点击一个连接&#xff0c;就是像服务器发起一个get请求&#xff0c;用户提交自己的信息是一个pos…

关于超长字符串/文本对应的数据从excel导入到PL/SQL中的尝试

问题&#xff1a; 1.字符串太长 2.str绑定之的结尾null缺失 将csv文件导入到PL/SQL表中存在的一些问题 1.本来我是需要将exceL上的几十条数据导入到PL/SQL数据库的一张表中&#xff0c;结果我花了许多时间 去导入。 想想一般情况下也就几十条数据&#xff0c;直接复制粘贴就…

C语言-有两个磁盘文件A和B,各存放一行字母,今要求把这两个文件的信息合并(按字母顺序排列),输出到一个新文件C中去-深度代码解析

&#x1f30f;个人博客&#xff1a;尹蓝锐的博客 1、题目要求 有两个磁盘文件A和B&#xff0c;各存放一行字母&#xff0c;今要求把这两个文件的信息合并&#xff08;按字母顺序排列&#xff09;&#xff0c;输出到一个新文件C中去 2、准备工作 问题1&#xff1a;为什么不需要…

chrome打印dom节点不显示节点信息

正常直接console dom节点 代码改成 var parser new DOMParser(); var docDom parser.parseFromString(testHtml, text/html); console.log(docDom) let htmlHeader ref< HTMLElement | null>(null) let htmlBoby ref< HTMLElement | null>(null) htmlHeader.v…

# 利刃出鞘_Tomcat 核心原理解析(九)-- Tomcat 安全

利刃出鞘_Tomcat 核心原理解析&#xff08;九&#xff09;-- Tomcat 安全 一、Tomcat专题 - Tomcat安全 - 配置安全 1、 删除 tomcat 的 webapps 目录下的所有文件&#xff0c;禁用 tomcat 管理界面. 如下目录均可删除&#xff1a; D:\java-test\apache-tomcat-8.5.42-wind…

深度学习入门-06

基于小土堆学习 如何把数据集和Transform结合袭来 https://pytorch.org/ 上述网址是pytorch的官网 这里会有详细的使用介绍 下述是对图像处理的专门文档 单击后可查看详细介绍 选择CIFAR10数据集 CIFAR10 数据集是一个广泛使用的计算机视觉数据集&#xff0c;包含了60000…

UV LED供电为什么要选择使用恒流驱动电源

LED为何一定要恒流供电? 在讨论此议题之前&#xff0c;什么是电源的恒流恒压&#xff1f; 什么是电源的恒流恒压   恒流&#xff0c;就是输出电流是恒定的&#xff0c;但电源电流却不是固定的&#xff0c;标称的电压只是安全上限&#xff1b;恒压&#xff0c;就是输出电压是…

Unity3D FixedUpdate处理物理模拟详解

在Unity3D中&#xff0c;处理物理模拟时&#xff0c;正确地使用FixedUpdate()方法是非常重要的。这是因为Unity的物理引擎&#xff08;PhysX&#xff09;是在固定的时间间隔内运行的&#xff0c;而不是像Update()那样每一帧都调用。这种设计旨在确保物理模拟的稳定性和可预测性…

力扣面试经典算法150题:跳跃游戏

跳跃游戏 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a;跳跃游戏。 题目链接&#xff1a;https://leetcode.cn/problems/jump-game/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 给定一个非负整数数组 nums&#xff0c;你最初…

uniapp/uniapp x总结

uni-app组成和跨端原理 上图所诉 App的渲染引擎&#xff1a;同时提供了2套渲染引擎&#xff0c;.vue页面文件由webview渲染&#xff0c;原理与小程序相同&#xff1b;.nvue页面文件由原生渲染&#xff0c;原理与react native相同。开发者可以根据需要自主选择渲染引擎。 uniapp…

R语言中theme的调整技巧汇总-持续更新

1.如何扩充图片的上右下左位置的空白区域&#xff1a; unit(c(1.1, 1, 0.4, 0.5), “cm”) 表示使用厘米作为单位设置各个方向的边距&#xff0c;c(1.1, 1, 0.4, 0.5) 对应的顺序是&#xff1a;上、右、下、左。 theme(plot.margin unit(c(1.1, 1, 0.4, 0.5), "cm")…

android gradle.properties 的作用

android gradle.properties 的作用 1 将多个应用程序打包成一个单一的应用程序&#xff08;超级应用或聚合应用&#xff09;在里面配置打包的版本&#xff0c;版本号&#xff0c;比如 version_code110 RELEASE_VERSION3.0.5 DEFAULT_BUILD_TYPE_NAMERelease 2 配置一些在线库&a…