您现在的位置是:首页 > 正文

golang panic recover return defer的逻辑顺序问题

2024-04-01 01:40:33阅读 1
package main

import "fmt"

//验证golang return  defer recover 之间的顺序关系

func main() {
	defer func() { //捕获panic
		fmt.Println("00000000")
		if r := recover(); r != nil {
			fmt.Println(r)
		}
	}()

	fmt.Println("let's go !!!")
	test1()
	test2()
	fmt.Println("it's over !!!") //test2() panic 之后所有的逻辑都不会在执行
}

func test1() {
	defer fmt.Println("333333")
	defer fmt.Println("222222") //return 之后运行 defer defer按照队列的形式 先进后出
	fmt.Println("1111111")
	return
	fmt.Println("4444444") //return之后不执行逻辑
}

func test2() {
	//defer func() { //如果在函数内部捕获panic  则函数上层的逻辑不会中断
	//	fmt.Println("ccccc")
	//	if r := recover(); r != nil {
	//		fmt.Println(r)
	//	}
	//}()
	defer fmt.Println("cccccc")
	fmt.Println("aaaaaaaaa")
	panic("this is a error !!!") //panic 之后 所有的逻辑都不会在执行
	fmt.Println("bbbbbbbbb")
}

结果:

let's go !!!
1111111
222222
333333
aaaaaaaaa
cccccc
00000000
this is a error !!!

通过test1函数可以看到return之后执行defer,并且defer是按照栈的顺序,先进后出的。test2函数中panic之前会先执行defer,之后会中断逻辑返回main函数,main函数在panic之后的逻辑

fmt.Println("it's over !!!")

不执行,接着去执行main函数的defer,recover捕捉到panic打印出来。

如果我们把test2修改成以下的样子:

func test2() {
	defer func() { //如果在函数内部捕获panic  则函数上层的逻辑不会中断
		fmt.Println("ddddddd")
		if r := recover(); r != nil {
			fmt.Println(r)
		}
	}()
	defer fmt.Println("cccccc")
	fmt.Println("aaaaaaaaa")
	panic("this is a error !!!") //panic 之后 所有的逻辑都不会在执行
	fmt.Println("bbbbbbbbb")
}

结果:

let's go !!!
1111111
222222
333333
aaaaaaaaa
cccccc
ddddddd
this is a error !!!
it's over !!!
00000000

可以看到在test2函数中加上defer recover,则main函数的之后逻辑会继续往下走,因为panic在test2中已经被拦截下来了,并没有走到main函数的defer recover。

总结:

1.return之后执行defer。
2.defer是按照栈的顺序执行,先进后出。
3.panic之后执行defer。
4.panic会中断流程,panic之后的逻辑不会运行。
5.如果不想影响主流程的逻辑应该在函数方法中recover。

网站文章

  • Unity Shader中的基础光照与标准光照模型(自发光、环境光、高光反射、漫反射)、BRDF光照模型

    Unity Shader中的基础光照与标准光照模型(自发光、环境光、高光反射、漫反射)、BRDF光照模型

    我们是如何看到这个世界的 从宏观上来说,渲染包含了两大部分 决定一个像素的可见性 决定这个像素上的关照计算 而光照模型就是用于决定一个像素上进行怎样的光照计算 通常来讲,我们要模拟真实的光照环境来生成...

    2024-04-01 01:40:27
  • Eclipse的使用(二)Eclipse插件的安装、升级和卸载

    Eclipse的使用(二)Eclipse插件的安装、升级和卸载

    Eclipse作为一个集成的IDE开发工具,为我们的软件开发提供了便利,eclipse除了自带的强大功能外,还支持功能丰富的插件。我们可以通过Eclipse官方市场 (http://marketplace.eclipse.org/)找到并下载我们需要的插件。  可以说Eclipse一切都是基于插件的,所以每使用一个功能就要装一次插件,所以掌握插件的安装、升级卸载是十分有必要的。  由于新版

    2024-04-01 01:40:20
  • 过滤html标记的函数

    过滤html标记的函数

     /**////   /// 过滤html  ///   ///   ///   public static string FilterSQL(string text)  ...{   string validSql = "";   if (text != null)   ...{    text = text.Replace(""", """);    text = text.

    2024-04-01 01:39:54
  • 分治算法

    分治算法

    一.分治算法的基本思想分治算法的基本思想是将一个计算复杂的问题分为规模较小、计算简单的小问题求解,然后综合各个小问题,得到最终的答案。大致执行的流程如下:1.对于一个规模为N的问题,若该问题比较容易解...

    2024-04-01 01:39:46
  • 【C语言】分支语句与循环语句

    【C语言】分支语句与循环语句

    前言 本篇记得是C语言中的分支和循环语句。 分支语句ifelse语句、switch语句 循环语句while循环、for循环、do while循环 语句 C语言中由一个分号;隔开的就是一条语句。比如: ...

    2024-04-01 01:39:41
  • nginx源码分析—reuseport的使用

    本文主要介绍nginx中reuseport的使用,文中代码较多,阅读本文需要读者对nginx的事件模块以及listen配置过程有了解。 由于nginx比较复杂,且作者对nginx的理解有限,文章难免存...

    2024-04-01 01:39:16
  • QNX中mmap_device_io() 和 mmap_device_memory()函数

    来源于QNX IDE 1、mmap_device_io() 1)函数定义 #include #include uintptr_t mmap_device_io( size_t len, uint64_t io ); len The number of bytes of device I/O memory that you want to access. It can'..

    2024-04-01 01:39:08
  • 位运算的一些技巧

    位运算的一些技巧

    1. 两个数异或:相当于每一位相加,而不考虑进位; 2. 两个数相与,并左移一位:相当于求得进位; 3. 一个数n与其减一的数相与(即n&(n-1)),等价于去掉最左边的1 如n=10二进制为1010,n&(n-1)=1000 应用以上技巧可以解决一些算法题: 下面是剑指offer上的一道题: class Solution { public: int Add(int n...

    2024-04-01 01:39:00
  • 互联互通、电子病历、智慧服务、智慧管理、公立医院绩效考核的5项测评

    互联互通、电子病历、智慧服务、智慧管理、公立医院绩效考核的5项测评

    互联互通、电子病历、智慧服务、智慧管理、公立医院绩效考核的5项测评

    2024-04-01 01:38:35
  • C++ 笔记 shared_from_this()的原理与使用

    shared_from_this()的用途 enable_shared_from_this是一个模板类,定义于头文件,其原型为: template< class T > class enable_shared_from_this; std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 st...

    2024-04-01 01:38:27