Golang语言异常机制解析:错误策略与优雅处理

 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。

前言

作为开发者来说,我们没办法保证程序在运行过程中永远不会出现异常,对于异常,在很多编程语言中,可以用 try-catch语句来捕获,而Go语言的开发者显然觉得 try-catch被滥用了,因此 Go不支持使用 try-catch语句捕获异常处理。

那么,Go语言是如何定义和处理程序的异常呢?

Go语言的将程序运行出现的问题分为两种:错误(error)和异常(exception),错误是程序(比如一个函数)运行的预期结果之一,当你调用一个函数时,就应该处理出现错误的情况,而异常是不可预期的(当然也可以手动触发)且会导致程序中断运行的严重错误。

目录

前言

Go错误处理策略

创建error的几种方式

errors包

fmt包

自定义错误类型

如何处理错误

直接返回错误

记录日志并继续运行

记录日志并结束运行

Go异常处理机制

panic函数

recover函数

总结

Go错误处理策略

编写Go语言程序,一般推荐通过函数的最后一个返回值告诉调用者函数是否执行成功,可以分两种情况来讨论:

第一种情况,如果函数的执行结果只有正确与失败,那么返回值可以是 boolean类型:

func exists(key string) bool {//to check if the key is existsreturn true
}if ok := exists("test"); ok {// do something
}

第二种情况,如果要让调用者得到更详细的错误信息,显然只返回一个布尔值是不够的,这时候可以返回一个 error类型,error类型是一个接口,只有一个 Error方法的接口:

type error interface {Error() string
}

通过 error类型的 Error方法,可以获得更详细的错误信息,方便调用者做进一步的处理,因此在 Go标准库的方法和函数中,一般都会将 error类型作为最后一个返回值,比如我们以前文章中讲到的 os包下的 Open和 Create函数:

package osfunc Open(name string) (*File, error) {return OpenFile(name, O_RDONLY, 0)
}func Create(name string) (*File, error) {return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

当函数最后一个返回值 error不为 nil时,表示执行不成功,此时其他的返回值就应该忽略:

file,err := os.Open("./my.dat")if err != nil{return err
}defer file.Close()

上面代码中,如果 error不为 nil,那么变量 file则为 nil,表示无法获得一个文件句柄,这时候直接返回错误,因为如果再继续往下执行,可能会引发程序崩溃。

当然并不是所有情况下一遇到返回的 error不为 nil,就要抛弃其他返回值,比如使用 Read()方法读取文件时:

Read(p []byte) (n int, err error)

在读取文件到结尾时 Read方法会返回一个 io.EOF的错误:

var EOF = errors.New("EOF")

此时虽然 error不为 nil,但仍然应该把读取到的字节数组保存,而不是抛弃掉。

创建error的几种方式

当我们开发自己的函数时,也可以创建自己的错误类型,有以下几种方式:

errors包

errors包下的 New()函数可以创建一个只有文本信息的 error类型:

package mainfunc main() {var s = []int{1, 2, 3}s[3] = 10
}
fmt包

fmt包下的 Errorf函数可以将文本格式后作为error类型的错误信息,并返回一个error类型,因此其作用与errors.New函数类似

func getFile(name string)(*os.file,error){if name == ""{return nil,fmt.Errorf("file name could not be empty")}
}

fmt.Errorf函数还能封装其他 error类型,再返回一个新的 error类型,以此形成一条完整的错误链条:

doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {return nil, fmt.Errorf("parsing %s as HTML: %v", url,err)
}
自定义错误类型

其实,上面两种创建错误类型的方式,本质上都是实现 error接口,我们也可以创建一个拥有 Error方法的类型来实现 error接口:

type Result struct {Code    intMessage stringData    interface{}
}func (r Result) Error() string {return r.Message
}

如何处理错误

当调用的函数或方法的返回值有 error类型时,最简单的当然可以选择直接忽略错误,不过更恰当的方式是处理对应的错误,有以下几种处理策略:

直接返回错误

对于函数来说,如果在执行时遇到错误,可以直接返回给上层调用者:

func SendMessage(url string) error {if url == ""{return errors.New("url can't not be empty")}_, err := http.Get(url)if err != nil {return err}return nil
}
记录日志并继续运行

当调用函数时遇到返回的错误,如果不影响程序运行,也可以选择记录错误日志并往下执行:

if err := SendMessage("https://xxx/sendMessage");err != nil{log.Printf("the message sending been broken by : %v\n", err)
}
记录日志并结束运行

如果错误影响程序的执行,也可以记录日志后,退出程序执行:

if err := SendMessage("https://xxx/sendMessage");err != nil{log.Printf("the message sending been broken by : %v\n", err)os.Exit(1)
}

记录日志并退出执行,直接用 log包的 Fatalf函数就可以做到,因此上面代码的更简洁做法是:

if err := SendMessage("https://xxx/sendMessage");err != nil{log.Fatalf("the message sending been broken by : %v\n", err)
}

Go异常处理机制

在Go语言中,异常是指会引发程序崩溃无法继续运行的错误,比如数组越界或者空指针引用等情况,这时候会触发 panic异常:

package mainfunc main() {var s = []int{1, 2, 3}s[3] = 10
}

上面程序运行结果如下,可以看出触发了数组越界的异常:

panic: runtime error: index out of range [3] with length 3

无论是在主协程还是子协程中,一旦触发 panic异常,整个程序都会终止运行。

panic函数

除了数组越界等不可预测的异常会自动触发 panic,也可以手动调用 panic函数触发异常来终止程序的运行:

func loadConfig(path string){panic("can't load the config file on path " + path)
}

一个良好的程序最好不要主动调用 panic函数,尤其是开发类库的时候,最好通过返回 error类型来告诉调用者发生了什么错误,而不是触发 panic导致程序终止运行。

recover函数

当发生 panic异常时,如果不捕获得异常,那么程序就是终止运行,在Go语言中,可以用 defer语句和 recover函数的模式来捕获 panic异常:

package mainimport ("fmt""log"
)func main() {n1 := FindElementByIndex(1)fmt.Println(n1)n2 := FindElementByIndex(4)fmt.Println(n2)
}func FindElementByIndex(index int) int {defer func() {if e := recover(); e != nil {log.Fatal(e)}}()s := []int{1, 2, 3, 4}return s[index]
}

总结

        本文深入探讨了Go语言的错误策略与异常机制。主要介绍了错误处理的重要性,以及Go语言中的错误类型和处理函数。此外还讨论了Go语言的异常机制,包括panic和recover函数的使用。通过合理的错误处理和异常处理,我们可以提高代码的可维护性和可靠性,减少潜在的bug和故障。希望本文对您有帮助,感谢阅读~

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

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

相关文章

docker镜像命令

docker images 列表本机上的镜像 - REPOSITORY:表示镜像的仓库源 - TAG:镜像的标签 - IMAGE ID:镜像 - ID CREATED:镜像创建时间 - SIZE:镜像大小 同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本&am…

C语言第十五弹---操作符(上)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 操作符 1、操作符的分类 2、二进制和进制转换 2.1、2进制转10进制 2.1.1、10进制转2进制数字 2.2、2进制转8进制和16进制 2.2.2、2进制转16进制 3. 原码、反…

计算机网络——网络层(3)

计算机网络——网络层(3) 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU)1 网络层——控制平面因特网中自治系统内部的路由选择总括考虑因素总结 ISP之间的路由选择:BGP考虑因素总结 SDN控制层面重要组件和功能总结 ICMP主要功能和特点…

Linux逻辑卷(LV)扩容

Linux逻辑卷(LV)扩容 1、准备物理磁盘(分区和不分区都行),可以使用lsblk命令查看新增的磁盘,如下图sde就是我们新增磁盘,容量为600G。 2、将新磁盘变成物理卷(PV) pvcr…

java:6 数组

文章目录 数组array1. 介绍2. 入门练习3. 数组的使用3.1 使用方法一:动态初始化3.2 使用方法二:动态初始化3.3 使用方法三:静态初始化 4. 数组的细节5. 数组的应用6. 数组赋值机制7. 数组拷贝8. 数组反转(2种) 数组arr…

Linux-----文本三剑客补充~

一、模糊匹配 模糊匹配用 ~ 表示包含,!~表示不包含 1、匹配含有root的列 [rootlocalhost ~]#awk -F: /root/ /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [rootlocalhost ~]#awk -F: $1~ /root/ /etc/passw…

vue插槽使用方法

细致讲解slot插槽的使用 彻底搞懂slot插槽,图文详解1、什么是插槽Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。插槽实质是对子组件的扩展,通过插槽向组件内部指定位置传递内容。slot的出现是为了父组件可以堂而皇之地在子…

RK3588平台开发系列讲解(视频篇)RKMedia的VDEC模块

文章目录 一、 VDEC模块支持的编码标准介绍二、VDEC API的调用三、VDEC解码流程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢RKMedia是RK提供的一种多媒体处理方案,可实现音视频捕获、音视频输出、音视频编解码等功能。 一、 VDEC模块支持的编码标准介绍 RK3688 V…

金航标kinghelm萨科微slkor宋仕强说

金航标kinghelm萨科微slkor宋仕强说,着眼未来,萨科微半导体将持续发挥自身在技术研发和产品创新方面的优势,以优质高效的半导体解决方案满足全球各地市场的需求。目前,萨科微的产品线已经囊括了二极管、三极管、功率器件、电源管理芯片等多个系列,并在霍尔传感器、A…

matlab中的图窗属性和坐标轴的属性

图窗的Position和Outerposition Position 指定窗口的尺寸和窗口在屏幕中的位置。 Outerposition 指定窗口外轮廓的大小和位置。 两者都是用一个4维向量来定义,格式为[左 底 宽 高]。 可通过set函数修改Position和Outerposition,如下:在屏幕左…

哪个牌子的头戴式耳机好?推荐性价比高的头戴式耳机品牌

随着科技的不断发展,耳机市场也呈现出百花齐放的态势,从高端的奢侈品牌到亲民的平价品牌,各种款式、功能的耳机层出不穷,而头戴式耳机作为其中的一员,凭借其优秀的音质和降噪功能,受到了广大用户的喜爱&…

如何在树莓派安装运行Nginx实现无公网ip环境访问内网静态网站

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 安装 Nginx(发音为“engine-x”)可以将您的树莓派变成一个强大的 Web 服务器,可以用于托管网站或 Web 应用程序。相比其他 Web 服务器,Ngi…