Go 错误处理

错误

在Go中有一部分函数总是能成功的运行。比如strings.Contains和strconv.FormatBool函数;对于大部分函数而言,永远无法确保能否成功运行。

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error类型是一个接口类型,这是它的定义:

type error interface { Error() string}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("math: square root of negative number") } // 实现}

这里有一个错误处理的例子

package mainimport “errors”import “fmt”// 按照惯例,错误通常是最后一个返回值并且是 error 类型,一个内建的接口。func f1(arg int) (int, error) {// errors.New 构造一个使用给定的错误信息的基本error 值。if arg == 42 {return -1, errors.New(“can’t work with 42”)}// 返回错误值为 nil 代表没有错误。return arg + 3, nil}// 通过实现 Error 方法来自定义 error 类型是可以的。// 这里使用自定义错误类型来表示上面的参数错误。type argError struct {arg intprob string}func (e *argError) Error() string {return fmt.Sprintf(“%d – %s”, e.arg, e.prob)}func f2(arg int) (int, error) {if arg == 42 {// 在这个例子中,我们使用 &argError 语法来建立一个新的结构体,并提供了 arg 和 prob 这个两个字段的值。return -1, &argError{arg, “can’t work with it”}}return arg + 3, nil}func main() {// 下面的两个循环测试了各个返回错误的函数。// 注意在 if行内的错误检查代码,在 Go 中是一个普遍的用法。for _, i := range []int{7, 42} {if r, e := f1(i); e != nil {fmt.Println(“f1 失败:”, e)} else {fmt.Println(“f1 工作:”, r)}}for _, i := range []int{7, 42} {if r, e := f2(i); e != nil {fmt.Println(“f2 失败:”, e)} else {fmt.Println(“f2 工作:”, r)}}// 你如果想在程序中使用一个自定义错误类型中的数据,你需要通过类型断言来得到这个错误类型的实例。_, e := f2(42)if ae, ok := e.(*argError); ok {fmt.Println(ae.arg)fmt.Println(ae.prob)}}

Deferred函数

defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后。

示例

package mainimport “fmt”import “os”func main() {// 假设我们想要创建一个文件,向它进行写操作,然后在结束时关闭它。// 这里展示了如何通过 defer 来做到这一切。f := createFile(“D:/defer.txt”) // f := createFile(“/tmp/defer.txt”)// 在 closeFile 后得到一个文件对象,我们使用 defer通过 closeFile 来关闭这个文件。这会在封闭函数(main)结束时执行,就是 writeFile 结束后。defer closeFile(f)writeFile(f)}func createFile(p string) *os.File {fmt.Println(“creating”)f, err := os.Create(p)if err != nil {panic(err)}return f}func writeFile(f *os.File) {fmt.Println(“writing”)fmt.Fprintln(f, “data”)}func closeFile(f *os.File) {fmt.Println(“closing”)f.Close()}

异常

Go的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起painc异常。

示例如下:

package mainimport (“fmt””os”)func main() {// 我们将在这个网站中使用 panic 来检查预期外的错误。这个是唯一一个为 panic 准备的例子。panic(“一个异常”)// panic 的一个基本用法就是在一个函数返回了错误值但是我们并不知道(或者不想)处理时终止运行。// 这里是一个在创建一个新文件时返回异常错误时的panic 用法。fmt.Println(“继续”)_, err := os.Create(“/tmp/file”)if err != nil {panic(err)}// 运行程序将会引起 panic,输出一个错误消息和 Go 运行时栈信息,并且返回一个非零的状态码。}

捕获异常

通常来说,不应该对panic异常做任何处理,但有时,也许我们可以从异常中恢复,至少我们可以在程序崩溃前,做一些操作。举个例子,当web服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何处理,会使得客户端一直处于等待状态。如果web服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。

如果在deferred函数中调用了内置函数recover,并且定义该defer语句的函数发生了panic异常,recover会使程序从panic中恢复,并返回panic value。导致panic异常的函数不会继续运行,但能正常返回。在未发生panic时调用recover,recover会返回nil。

示例:

package mainimport “fmt”func main() {// 这里我们对异常进行了捕获defer func() {if p := recover(); p != nil {err := fmt.Errorf(“internal error: %v”, p)if err != nil {fmt.Println(err)}}}()// 我们将在这个网站中使用 panic 来检查预期外的错误。这个是唯一一个为 panic 准备的例子。panic(“一个异常”)}

分享不易,欢迎大家点赞关注~~~ 感谢大家阅读!

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年6月20日
下一篇 2022年6月20日

相关推荐

  • 5个暗藏惊喜的微信小程序,个个好用不要钱,请你低调使用

    相比于手机App,我更喜欢用微信小程序,不用下载安装,便捷的同时还节省了手机内存。下面这5个暗藏惊喜的微信小程序,个个好用不要钱,请大家低调使用。 01*工具箱 这是一个非常实用的…

    2022年9月20日
  • 「go商城」gin+gorm实现CRUD

    gorm是什么? ORM-Object-Relationl Mapping,即对象关系映射,这里的Relationl指的是关系型数据库它的作用是在关系型数据库和对象之间作一个映射,…

    2022年6月28日
  • 小米公布自动驾驶相关专利,可实现“自动超车”

    记者 | 佘晓晨 小米造车又有新进展。天眼查App显示,近日,小米汽车科技有限公司申请的“自动超车方法、装置、车辆、存储介质及芯片”专利公布。 值得一提的是,此次公布的专利涉及自动…

    2022年6月15日
  • Java实现在线SQL编程(完整版)

    前言: 由于前段时间,项目组长分配的任务是要完成一个在线编写 SQL 并要实现查询功能的需求,最终需要将查询到的数据以 JSON 格式显示到响应数据的区域,以供操作者进行查看,一开…

    2022年6月23日
  • 这么好用的三星多屏联动功能,竟然还有人不知道?

    哈喽啊 各位小伙伴们, 又到了有趣且实用的三星功能分享时间啦~ 在分享今天的功能之前, 想问一下大家在日常生活中, 是用什么样的方式进行手机与 平板/电脑之间的屏幕共享的呢~ 很多…

    2022年6月29日
  • springboot、mybatis-plus、Druid多数据源环境搭建

    简述 Java单体项目里,我们一般是只需配置一个数据库,这时代码里的dao层都是只对一个数据库操作;但有时候我们的数据可能在2个或者3个数据库,这时就需要配置更多数据源,进行数据库…

    2022年6月21日
  • 等红灯时,为什么有些人会一直踩着刹车?

    等红灯时,为什么有些人会选择一直踩着刹车?这道题问的挺有趣的,不一直踩着刹车、难道要踩油门么?踩油门就闯红灯了!所以自动档车等红灯无论是挂D、N都应该带点刹车,这也是出于安全角度的…

    2022年7月24日
  • 怎样找回支付宝原始支付密码(支付宝密码忘记了怎么办)

    在线购物和离线移动支付需要支付宝,也可以用支付宝支付各种生活费用。可以说,支付宝在当今流行的移动支付中占有重要地位。每个身份证只能拥有一个支付宝。如果忘记支付宝密码,虽然麻烦很多,…

    2022年11月2日
  • Mongodb和mysql的区别

    Mongodb和mysql的区别 1.Mongodb简介及优缺点分析 Mongodb是非关系型数据库(nosql ),属于文档型数据库。文档是mongoDB中数据的基本单元,类似关…

    2022年6月22日
  • 江苏省交通综合执法局“工程云专家”平台正式上线

    【来源:中国水运网】 近日,江苏省交通运输综合行政法监督局精心打造的“工程云专家”平台正式上线。 “工程云专家”基于“工程专家”微信小程序开发,汇聚了大量行业资深专家。平台突破了线…

    2022年6月29日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息