一文掌握Golang的panic和recover实战

 更新时间:2024年09月10日 15:48:17   作者:CodeJR  
Go语言中,异常处理通常依赖error返回值,本文将通过示例展示如何在Go语言中正确使用recover来处理panic异常,防止程序直接崩溃,感兴趣的朋友跟随小编一起看看吧

简述

我们都知道在Go语言中的异常处理是通过方法返回error,然后在调用方法处接收error并处理,这里的error通常是使用在业务异常的处理。

如果程序发生数组越界、空指针等异常就不会再通过error来处理,而是通过panic直接报错并终止程序和打印出堆栈信息。那么如何在程序发生panic的时候去处理这个异常而不是终止程序呢?这个时候就需要使用到recover,recover可以捕获到panic异常,并恢复程序的运行。

panic

  • 调用panic后立即终止执行当前函数的剩余代码,在当前goroutine中执行当前函数所有的defer
  • panic只会触发当前goroutine的defer

recover

  • 调用recover可以捕获panic的异常,并恢复程序的执行
  • recover只在defer延迟函数中调用才会生效

实战

示例1

我们首先在代码中直接使用recover捕获异常,并使用panic手动抛出一个异常,看看程序会怎么样

func main() {
	test()
	fmt.Println("main")
}
func test() {
	if err := recover(); err != nil {
		fmt.Println("recover: ", err)
	}
	panic("error")
}

运行上面的代码之后可以从输出看到在test函数中发生了panic,并且直接终止运行,导致main函数中的打印也没有生效,这是因为在前面的时候有讲到过,recover必须在defer延迟函数中调用才会生效。

panic: error                                                    
goroutine 1 [running]:                                          
main.test()                                                     
        C:/Users/lee/GolandProjects/test/main.go:33 +0x30
main.main()                                                     
        C:/Users/lee/GolandProjects/test/main.go:24 +0x13

示例2

修改上面的代码,将recover放到defer延迟函数中调用:

func main() {
	test()
	fmt.Println("main")
}
func test() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("recover: ", err)
		}
	}()
	panic("error")
}

这个时候我们再次运行代码,可以看到虽然在test函数中发生了panic,但是程序并没有终止运行,而是被defer中的recover捕获到了异常并恢复运行,同时main函数中的print也正常打印。

recover:  error
main

示例3

上面示例2中将recover是放到defer的函数中调用,那么如果在defer后面直接调用recover会生效吗?使用下面代码进行测试。

func main() {
	test()
	fmt.Println("main")
}
func test() {
	defer recover()
	panic("error")
}

运行上面的代码之后发现在defer后面直接调用recover是无效的,程序照样会发生异常并终止运行,所以**recover必须是在defer的延迟函数中调用才会生效。**示例2中是匿名延迟函数,如果使用具名延迟函数同样有效。

panic: error
goroutine 1 [running]:
main.test()
        C:/Users/lee/GolandProjects/test/main.go:30 +0x58
main.main()
        C:/Users/lee/GolandProjects/test/main.go:24 +0x13

示例4

上面说到过recover必须在defer的延迟函数中调用,那下面的代码可以生效吗?

func main() {
	test()
	fmt.Println("main")
}
func test() {
	defer func() {
		defer recover()
	}()
	panic("error")
}

运行上面的代码可以看到recover是生效的,recover函数被一个延迟函数调用,且recover函数本身作为一个延迟函数,这个情况下也是可以正常捕获panic异常的,程序运行如下:

main

到此这篇关于一文掌握Golang的panic和recover的文章就介绍到这了,更多相关Golang panic和recover内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Goland 关闭自动移除未使用的包操作

    Goland 关闭自动移除未使用的包操作

    这篇文章主要介绍了Goland 关闭自动移除未使用的包操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 用Go写一个轻量级的ssh批量操作工具的方法

    用Go写一个轻量级的ssh批量操作工具的方法

    这篇文章主要介绍了用Go写一个轻量级的ssh批量操作工具的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • goFrame的gqueue与channe的区别

    goFrame的gqueue与channe的区别

    这篇文章主要介绍了goFrame的gqueue与channe的区别,channel的作用是用于go协程间的通信,goroutine和channel是支持高并发的重要组成部分,更多两者详细介绍需要的小伙伴可以参考下面文章内容
    2022-06-06
  • 基于Go编写一个Windows剪贴板监控器

    基于Go编写一个Windows剪贴板监控器

    这篇文章主要为大家详细介绍了如何基于Go编写一个Windows剪贴板监控器,可以在后台默默监听你的复制行为,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-11-11
  • Golang 定时器(Timer 和 Ticker),这篇文章就够了

    Golang 定时器(Timer 和 Ticker),这篇文章就够了

    这篇文章主要介绍了Golang 定时器(Timer 和 Ticker),这篇文章就够了,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Go中零值与空值的实现与区别

    Go中零值与空值的实现与区别

    本文主要介绍了Go中零值与空值的实现与区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • go语言go func(){select{}}()的用法

    go语言go func(){select{}}()的用法

    本文主要介绍了go语言go func(){select{}}()的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • 使用Go语言实现敏感词过滤功能

    使用Go语言实现敏感词过滤功能

    敏感词过滤,算是一个比较常见的功能,尤其是在内容、社交类应用中更是如此,本文介绍如何使用Go语言实现简单的敏感词过滤功能,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Go log模块的使用技巧

    Go log模块的使用技巧

    Golog模块是一个强大的日志记录库,提供了丰富的功能,如线程安全的日志记录、灵活的日志格式配置、多种输出目标支持等,它还提供了错误处理和程序终止功能,以及自定义Logger的创建,本文给大家介绍Go log模块的使用,感兴趣的朋友一起看看吧
    2025-11-11
  • 手把手教你如何在Goland中创建和运行项目

    手把手教你如何在Goland中创建和运行项目

    欢迎来到本指南!我们将手把手地教您在Goland中如何创建、配置并运行项目,通过简单的步骤,您将迅速上手这款强大的集成开发环境(IDE),轻松实现您的编程梦想,让我们一起开启这段精彩的旅程吧!
    2024-02-02

最新评论