Go语言异常处理案例解析
作者:极客江南 发布时间:2024-02-04 07:26:02
异常处理
程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常
golang中提供了两种处理异常的方式
一种是程序发生异常时, 将异常信息反馈给使用者
一种是程序发生异常时, 立刻退出终止程序继续运行
打印异常信息
Go语言中提供了两种创建异常信息的方式
方式一: 通过fmt包中的Errorf函数创建错误信息, 然后打印
package main
import "fmt"
func main() {
// 1.创建错误信息
var err error = fmt.Errorf("这里是错误信息")
// 2.打印错误信息
fmt.Println(err) // 这里是错误信息
}
方式二: 通过errors包中的New函数创建错误信息,然后打印
package main
import "fmt"
func main() {
// 1.创建错误信息
var err error = errors.New("这里是错误信息")
// 2.打印错误信息
fmt.Println(err) // 这里是错误信息
}
两种创建异常信息实现原理解析
Go语言中创建异常信息其实都是通过一个error接口实现的
Go语言再builtin包中定义了一个名称叫做error的接口. 源码如下
package builtin
// 定义了一个名称叫做error的接口
// 接口中声明了一个叫做Error() 的方法
type error interface {
Error() string
}
在errors包中定义了一个名称叫做做errorString的结构体, 利用这个结构体实现了error接口中指定的方法
并且在errors 包中还提供了一个New方法, 用于创建实现了error接口的结构体对象, 并且在创建时就会把指定的字符串传递给这个结构体
// 指定包名为errors
package errors
// 定义了一个名称叫做errorString的结构体, 里面有一个字符串类型属性s
type errorString struct {
s string
}
// 实现了error接口中的Error方法
// 内部直接将结构体中保存的字符串返回
func (e *errorString) Error() string {
return e.s
}
// 定义了一个New函数, 用于创建异常信息
// 注意: New函数的返回值是一个接口类型
func New(text string) error {
// 返回一个创建好的errorString结构体地址
return &errorString{text}
}
fmt包中Errorf底层的实现原理其实就是在内部自动调用了errors包中的New函数
func Errorf(format string, a ...interface{}) error {
return errors.New(Sprintf(format, a...))
}
应用场景
package main
import "fmt"
func div(a, b int) (res int, err error) {
if(b == 0){
// 一旦传入的除数为0, 就会返回error信息
err = errors.New("除数不能为0")
}else{
res = a / b
}
return
}
func main() {
//res, err := div(10, 5)
res, err := div(10, 0)
if(err != nil){
fmt.Println(err) // 除数不能为0
}else{
fmt.Println(res) // 2
}
}
中断程序
Go语言中提供了一个叫做panic函数, 用于发生异常时终止程序继续运行
package main
import "fmt"
func div(a, b int) (res int) {
if(b == 0){
//一旦传入的除数为0, 程序就会终止
panic("除数不能为0")
}else{
res = a / b
}
return
}
func main() {
res := div(10, 0)
fmt.Println(res)
}
Go语言中有两种方式可以触发panic终止程序
我们自己手动调用panic函数
程序内部出现问题自动触发panic函数
package main
import "fmt"
func main() {
// 例如:数组角标越界, 就会自动触发panic
var arr = [3]int{1, 3, 5}
arr[5] = 666 // 报错
fmt.Println(arr)
// 例如:除数为0, 就会自动触发panic
var res = 10 / 0
fmt.Println(res)
}
除非是不可恢复性、导致系统无法正常工作的错误, 否则不建议使用panic
恢复程序
程序和人一样都需要具备一定的容错能力, 学会知错就改. 所以如果不是不可恢复性、导致系统无法正常工作的错误, 如果发生了panic我们需要恢复程序, 让程序继续执行,并且需要记录到底犯了什么错误
在Go语言中我们可以通过defer和recover来实现panic异常的捕获, 让程序继续执行
package main
import "fmt"
func div(a, b int) (res int) {
// 定义一个延迟调用的函数, 用于捕获panic异常
// 注意: 一定要在panic之前定义
defer func() {
if err := recover(); err != nil{
res = -1
fmt.Println(err) // 除数不能为0
}
}()
if(b == 0){
//err = errors.New("除数不能为0")
panic("除数不能为0")
}else{
res = a / b
}
return
}
func setValue(arr []int, index int ,value int) {
arr[index] = value
}
func main() {
res := div(10, 0)
fmt.Println(res) // -1
}
panic注意点
panic异常会沿着调用堆栈向外传递, 所以也可以在外层捕获
package main
import "fmt"
func div(a, b int) (res int) {
if(b == 0){
//err = errors.New("除数不能为0")
panic("除数不能为0")
}else{
res = a / b
}
return
}
func main() {
// panic异常会沿着调用堆栈向外传递, 所以也可以在外层捕获
defer func() {
if err := recover(); err != nil{
fmt.Println(err) // 除数不能为0
}
}()
div(10, 0)
}
多个异常,只有第一个会被捕获
package main
import "fmt"
func test1() {
// 多个异常,只有第一个会被捕获
defer func() {
if err := recover(); err != nil{
fmt.Println(err) // 异常A
}
}()
panic("异常A") // 相当于return, 后面代码不会继续执行
panic("异常B")
}
func main() {
test1(10, 0)
}
如果有异常写在defer中, 那么只有defer中的异常会被捕获
package main
import "fmt"
func test2() {
// 如果有异常写在defer中, 并且其它异常写在defer后面, 那么只有defer中的异常会被捕获
defer func() {
if err := recover(); err != nil{
fmt.Println(err) // 异常A
}
}()
defer func() {
panic("异常B")
}()
panic("异常A")
}
func main() {
test1(10, 0)
}
来源:https://blog.csdn.net/weixin_44617968/article/details/117697865
猜你喜欢
- 内容简介展示如何给图像叠加不同等级的椒盐噪声和高斯噪声的代码,相应的叠加噪声的已编为对应的类,可实例化使用。以下主要展示自己编写的:加噪声的
- 操作如下:(1)将SQL安装光盘(或者ISO)放进去运行,进入安装界面。 (也可进入开始》程序》Microsoft SQL Server 2
- 1.if判断1.1 if语句if 表达式:语句1语句2……1.“if&
- 正则表达式中的符号符号描述re1 | re2匹配正则表达式 re1 或者 re2 ;re1 与 re2 代表两个匹配的字符串信息^匹配字符串
- 问题描述??输入一个正整数n在n*n的方阵内填入1,2,3,4…n*n,要求填成蛇形。(回旋的向中间收敛)样例输入:4样例输出:不必严格按照
- 这里将更新最新的最全面的read_csv()函数功能以及参数介绍,参考资料来源于官网。pandas库简介官方网站里详细说明了pandas库的
- 人工智能是一个很广阔的领域,很多编程语言都可以用于人工智能开发,所以很难说人工智能必须用哪一种语言来开发。选择多也意味着会有优劣之分,并不是
- 还是网站在不同操作系统不同浏览器下兼容性的问题,但难度加了一层.如果是要检查用户登录后的页面的兼容性,该怎么办?现在一般的测试网站,都是提交
- 如何显示存储在BLOB字段中的图像?showimges.asp' 在浏览器上单独显示图像 <%@ 
- 安装 php首先安装 php 的压缩包,目前下载地址解压文件到这个路径下:D:\Program Files\php-7.3.5(自行选择合适
- 相信没有人不知道 Firebug 是什么东西,但有时候我们糟糕的代码不想让同行轻松的使用 F12 就能一览无遗。那么怎么办呢?这里有个猥琐的
- 首先要扩展自带的auth_user表我就放个图吧,同时setting中应该设置:# 此处重载是为了使UserProfile生效AUTH_US
- 1.彻底弄懂CSS盒子模式一(DIV布局快速入门) 2.彻底弄懂CSS盒子模式二(导航栏实例) 3.彻底弄懂CSS盒子模式三(浮动的表演和清
- Python 风格规范(Google)本项目并非 Google 官方项目, 而是由国内程序员凭热情创建和维护。如果你关注的是 Google
- PyQt实现界面翻转切换效果是用qt的场景功能来实现的,用到了QGraphicsView,QGraphicsLinearLayout,QGr
- 1.使用open()函数打开文件夹在读取一个文件的内容之前,需要先打开这个文件。在Python程序中可以通过内置函数open()来打开一个文
- 模块介绍:from ftplib import FTP ftp = FTP() #设置变量 ftp.set_debuglevel(2) #打
- python遍历字符串中的每一个字符有4种方式:1. for in ;2.iter内置函数;3.内置函数range()或xrange();4
- 经过一段时间的开发与测试,终于发布了Lms框架的第一个正式版本(1.0.0版本),并给出了lms框架的样例项目lms.samples。本文通
- 前言ctypes是Python的外部函数库。它提供了C兼容的数据类型,并且允许调用动态链接库/共享库中的函数。它可以将这些库包装起来给Pyt