一文详细谈谈GoLang的panic和error
作者:渣渣帅 发布时间:2024-05-13 10:45:15
前言
首先说一下: 错误指的是可能出现问题的地方出现了问题。如打开件失败,这种情况在意料之中 。异常指的是不应该出现问题的地方出现了问题。如引用了空指针,这种情况在意料之外
Go
提供两种错误处理方式
函数返回
error
类型对象判断错误panic
异常
1. panic
Go的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起painc异常。
一般而言,当panic异常发生时,程序会中断运行,并立即执行在该goroutine(可以先理解成线程)中被延迟的函数(defer 机制)。随后,程序崩溃并输出日志信息。日志信息包括panic value和函数调用的堆栈跟踪信息。panic value通常是某种错误信息。对于每个goroutine,日志信息中都会有与之相对的,发生panic时的函数调用堆栈跟踪信息。通常,我们不需要再次运行程序去定位问题,日志信息已经提供了足够的诊断依据。因此,在我们填写问题报告时,一般会将panic异常和日志信息一并记录。不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常;panic函数接受任何值作为参数。当某些不应该发生的场景发生时,我们就应该调用panic。虽然Go的panic机制类似于其他语言的异常,但panic的适用场景有一些不同。由于panic会引起程序的崩溃,因此panic一般用于严重错误,如程序内部的逻辑不一致。
panic
可以手工调用,但是 Go
官方建议尽量不要使用panic
,每一个异常都应该用 error
对象捕获。如果异常出现了,但没有被捕获并恢复,Go
程序的执行就会被终止,即便出现异常的位置不在主 Goroutine
中也会这样。
总结来说:
panic是一个严重错误机制,它会导致程序终止,并依次逆序执行 panic 所在函数可能存在的 defer 函数列表,然后返回该函数的调用方。recover 内置函数可用于捕获 panic,重新恢复程序正常执行流程,但是 recover 函数只有在 defer 内部使用才有效
此外,当 panic()
触发的宕机发生时, panic()
后面的代码将不会被运行,但是在 panic()
函数前面已经运行过的 defer
语句依然会在宕机发生时发生作用
2. recover
1. recover
是一个 Go
语言的内建函数,可以让进入宕机流程中的 goroutine
恢复过来。
2. 用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为
3. 一般的调用建议
a). 在defer函数中,通过recever来终止一个gojroutine的panicking过程,从而恢复正常代码的执行
b). 可以获取通过panic传递的error
简单来讲:go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。
4. 在正常的执行过程中,调用 recover
会返回 nil
并且没有其他任何效果;
注意:利用recover处理panic指令,defer必须在panic之前声明,否则当panic时,recover无法捕获到panic.
总结来说 Go
语言没有异常系统,其使用 panic
触发宕机类似于其他语言的抛出异常, recover
的宕机恢复机制就对应其它语言中的 try/catch
机制。
panic 和 recover 的关系
panic 和 recover 的组合有如下特性:
有 panic 没 recover ,程序宕机。
有 panic 也有 recover ,程序不会宕机,执行完对应的 defer 后,从宕机点退出当前函数后继续执行。
注意:在 panic 触发的 defer 函数内,可以继续调用 panic ,进一步将错误外抛,直到程序整体崩溃。如果想在捕获错误时设置当前函数的返回值,可以对返回值使用命名返回值方式直接进行设置。
示例:
package main
func test() {
defer func() {
if err := recover(); err != nil { // recover 捕获错误。
println(err.(string)) // 将 interface{} 转型为具体类型。
}
}()
panic("panic error!")// panic 抛出错误
}
func main() {
test()
}
3. error
go中的错误处理,是通过返回值的形式来出来,要么你忽略,要么你处理(处理也可以是继续返回给调用者),对于golang这种设计方式,我们会在代码中写大量的if判断,以便做出决定。
对于err如果是nil就代表没有错误,如果不是nil就代表程序出问题了,需要对错误进行处理了。
示例:
func main() {
conent,err:=ioutil.ReadFile("filepath")
if err !=nil{
//错误处理
}else {
fmt.Println(string(conent))
}
}
此外,error类型是go语言的一种内置类型,使用的时候不用特定去import,他本质上是一个接口,
type error interface{
Error() string //Error()是每一个订制的error对象需要填充的错误消息,可以理解成是一个字段Error
}
来源:https://blog.csdn.net/qq_39458487/article/details/124798684
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 系统管理员通常从svn/git中检索代码,部署站点后通常首先会生成该站点所有文件的MD5值,如果上线后网站页面内容被篡改(如挂马)等,可以比
- vscode 的调试功能其实提供了一键编译运行的功能(ctrl+F5),但是启动特别特别慢… 又不想安装插件,后来发现vscode 提供了一
- 我们准备如下两个表,并插入数据。#分类CREATE TABLE IF NOT EXISTS `type` (`id` INT(10) UNS
- 有时我们需要将一份或者多份PDF文件中的图片提取出来,如果采取在线的网站实现的话又担心图片泄漏,手动操作又觉得麻烦,其实用Python也可以
- 前言随着深度学习的不断发展,从开山之作Alexnet到VGG,网络结构不断优化,但是在VGG网络研究过程中,人们发现随着网络深度的不断提高,
- 有朋友问,在数据库中如何查询数据所在的行,一般我们建议一个自增字段就可以了.但是有时却会删除数据,那么那个自增字段也不正确了先不管朋友们为什
- 本文实例讲述了Python实现约瑟夫环问题的方法。分享给大家供大家参考,具体如下:题目:0,1,...,n-1这n个数字排成一个圆圈,从数字
- 解决中文乱码问题项目地址 github: https://github.com/Delgan/loguru文档:https://loguru
- <div id="d1"></div> <script > fu
- 一. 删除完全重复的记录完全重复的数据,通常是由于没有设置主键/唯一键约束导致的。测试数据:if OBJECT_ID('duplic
- 现象:已知,连接的WIFI网络需要通过代理服务器才能连接外网,按照正常的程序无法发送邮件,而直连一个没有代理的网络【如自己的wifi热点】,
- 在web开发中经常遇到多关键词对对单个字段查询,我一般是通过动态数组来实现的。当然多个关键词的一般是用空格或,隔开,我这几假设多个关键词用空
- 迭代是 Python 中的基本操作。我们可以迭代列表、字符串和所有其他结构。Asyncio 允许我们开发异步迭代器。我们可以通过定义一个实现
- MySQL中模式就是数据库SHOW DATABASES;show databases;罗列所有数据库名称CREATE DATABASE &l
- 本文实例讲述了js实现黑色简易的滑动门网页tab选项卡效果。分享给大家供大家参考。具体如下:这是一款js实现的黑色风格网页滑动门菜单,虽然简
- 1.使用 urllib2 实现#! /usr/bin/env python# -*- coding=utf-8 -*- import url
- 上次学会了爬取图片,这次就想着试试爬取商家的联系电话,当然,这里纯属个人技术学习,爬取过后及时删除,不得用于其它违法用途,一切后果自负。首先
- # 贪婪模式 默认的匹配规则# 在满足条件的情况下 尽可能多的去匹配到字符串import rers = re.match('\d{6
- 一、前言为方便描述教程例子,这里给出mysql表结构定义和golang结构体定义。下面是教程用到的foods表结构定义:CREATE TAB
- 例子老规矩,先上一个代码:def add(s, x): return s + xdef gen(): for i in range(4):