文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

聊聊Go 语言的错误处理

2024-12-03 06:00

关注
  1. type error interface { 
  2.   Error() string 

调用该方法,会返回当前错误的具体结果。一般有下面几种方式生成 error。

errors.New()

调用 errors.New() 会返回一个 error 类型的结构体,该结构体内部会实现一个 Error() 方法, 调用该方法返回的结果为调用 errors.New() 方法时传入的内容。

  1. import ( 
  2.  "errors" 
  3.  "fmt" 
  4.  
  5. func divide(a, b int) (error, int) { 
  6.  if b == 0 { 
  7.     // 被除数为0,则构造一个 error 结构体 
  8.   return errors.New("被除数不能为0"), 0 
  9.  } 
  10.  var result = a / b 
  11.  return nil, result 
  12.  
  13. func main() { 
  14.  var err error // error 类型数据的初始值为 nil,类似于 js 中的 null 
  15.  var result int 
  16.  
  17.  err, result = divide(1, 0) 
  18.  
  19.   if err == nil { 
  20.     // 如果 err 为 nil,说明运行正常 
  21.     fmt.Println("计算结果", result) 
  22.   } else { 
  23.     // 如果 err 不为 nil,说明运行出错 
  24.     // 调用 error 结构体的 Error 方法,输出错误原因 
  25.     fmt.Println("计算出错", err.Error()) 
  26.   } 

可以看到,上面的代码中,由于调用 divide 除法方法时,由于传入的被除数为 0。经过判断,会抛出一个由 errors.New 构造的 error 类型的结构体。

我们将调用 error.Error() 方法返回的结果输出到控制台,可以发现其返回的结果,就是传入 New 方法的值。

执行结果如下:

fmt.Errorf()

通过 fmt.Errorf() 方法构造的 error 结构体,与调用 errors.New() 方法的结果类似。不同的是,fmt.Errorf() 方法会进行一次数据的格式化。

  1. func divide(a, b int) (error, int) { 
  2.  if b == 0 { 
  3.     // 将参数进行一次格式化,格式化后的字符串放入 error 中 
  4.   return fmt.Errorf("数据 %d 不合法", b), 0 
  5.  } 
  6.  var result = a / b 
  7.  return nil, result 
  8.  
  9. err, result := divide(1, 0) 
  10. fmt.Println("计算出错", err.Error()) 

执行结果如下:

panic() 与 recover()

panic()

panic() 相当于主动停止程序运行,调用时 panic() 时,需要传入中断原因。调用后,会在控制台输出中断原因,以及中断时的调用堆栈。我们可以改造一下之前的代码:

  1. func divide(a, b int) (error, int) { 
  2.  if b == 0 { 
  3.     // 如果程序出错,直接停止运行 
  4.   panic("被除数不能为0"
  5.  } 
  6.  var result = a / b 
  7.  return nil, result 
  8.  
  9. func main() { 
  10.   err, result := divide(1, 0) 
  11.   fmt.Println("计算出错", err.Error()) 

在运行到 panic() 处,程序直接中断,并在控制台打印出了中断原因。

panic() 可以理解为,js 程序中的 throw new Error() 的操作。那么,在 go 中有没有办法终止 panic() ,也就是类似于 try-catch 的操作,让程序回到正常的运行逻辑中呢?

recover()

在介绍 recover() 方法之前,还需要介绍一个 go 语言中的另一个关键字:defer。

defer 后的语句会在函数进行 return 操作之前调用,常用于资源释放、错误捕获、日志输出。

  1. func getData(table, sql) { 
  2.   defer 中断连接() 
  3.   db := 建立连接(table
  4.   data := db.select(sql) 
  5.   return data 

defer 后的语句会被存储在一个类似于栈的数据结构内,在函数结束的时候,被定义的语句按顺序出栈,越后面定义的语句越先被调用。

  1. func divide(a, b intint { 
  2.   defer fmt.Println("除数为", b) 
  3.   defer fmt.Println("被除数为", a) 
  4.  
  5.   result := a / b 
  6.   fmt.Println("计算结果为", result) 
  7.  return result 
  8.  
  9. divide(10, 2) 

上面的代码中,我们在函数开始运行的时候,先通过 defer 定义了两个输出语句,先输出除数,后输出被除数。

实际的运行结果是:

这和前面提到的,通过 defer 定义的语句会在函数结束的时候,按照出栈的方式进行执行,先定义的后执行。defer 除了会在函数结束的时候执行,出现异常的的时候也会先走 defer 的逻辑,也就是说,我们在调用了 panic() 方法后,程序中断过程中,也会先将 defer 内的语句运行一遍。

这里我们重新定义之前的 divide 函数,在执行之前加上一个 defer 语句,defer 后面为一个自执行函数,该函数内会调用 recover() 方法。

recover() 方法调用后,会捕获到当前的 panic() 抛出的异常,并进行返回,如果没有异常,则返回 nil。

  1. func divide(a, b intint { 
  2.   // 中断之前,调用 defer 后定义的语句 
  3.  defer func() { 
  4.   if err := recover(); err != nil { 
  5.    fmt.Println("捕获错误", err) 
  6.   } 
  7.  }() 
  8.  
  9.  if b == 0 { 
  10.     // 函数运行被中断 
  11.   panic("被除数不能为0"
  12.   return 0 
  13.  } 
  14.  
  15.  return a / b 
  16.  
  17. result := divide(1, 0) 
  18. fmt.Println("计算结果", result) 

上面的代码运行后,我们发现之前调用 panic() 中断的程序被恢复了,而且后面的计算结果也正常进行输出了。

这就有点类似于 try-catch 的逻辑了,只是 recover 需要放在 defer 关键词后的语句中,更像是 catch 和 finally 的结合。

本文转载自微信公众号「自然醒的笔记本」,可以通过以下二维码关注。转载本文请联系自然醒的笔记本公众号。

 

来源:自然醒的笔记本内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯