go 如何捕获异常

简介: go 如何捕获异常

什么是异常?


不按照我们期望执行的都可以称之为异常

在Go语言中如何处理异常?


  • 一种是程序发生异常时, 将异常信息反馈给使用者
  • 一种是程序发生异常时, 立刻退出终止程序继续运行

将异常信息反馈给使用者


  • 创建方式一: fmt.Errorf("提示的内容")
  • 创建方式二: errors.New("提示的内容")注意点: 本质上两个方法底层的实现原理都是一样的

package builtin中定义了一个接口


type error interface {
   Error() string
}


package errors中定义了一个结构体


type errorString struct {
   s string
}


errorString结构体实现了builtin中定义的接口


func (e *errorString) Error() string {
   return e.s
}


所以errorString结构体实现了error接口


func New(text string) error {
   return &errorString{text}
}


异常信息提示


func TestThrowError(t *testing.T) {
 if res, err := div(10, 0); err == nil {
  fmt.Println(res)
 } else {
  fmt.Println(err)
 }
}
func div(a int, b int) (res int, err error) {
 if b == 0 {
  // 创建异常的两种方式
  err = fmt.Errorf("除数不能为0")
  err = errors.New("除数不能为0")
 } else {
  res = a / b
 }
 return res, err
}


运行结果:


=== RUN   TestThrowError
除数不能为0
--- PASS: TestThrowError (0.00s)
PASS


异常处理终止程序


程序终止的方式:

  • 系统自动终止
  • 手动终止(企业级应用开发中不常用)格式 :panic("提示信息")
func TestExceptionPanic(t *testing.T) {
 /*
    一种是程序发生异常时, 立刻退出终止程序继续运行
    终止程序也分为两种:
    1.系统自动终止
    2.我们手动终止 (企业开发不常用)
    格式: panic("提示信息")
 */
 // 系统自动终止
 //arr := [3]int{1, 3, 5}
 //for i := 0; i < 20; i++ {
 // fmt.Println(arr[i])
 //}
 res := div1(10, 0)
 fmt.Println(res)
}
// 除法运算
func div1(a int, b int) (res int) {
 if b == 0 {
  //手动终止程序
  panic("除数不能为0")
 } else {
  res = a / b
 }
 return res
}


异常恢复


  • 程序不要随意被终止,只要不是程序不能运行,需要建立让程序保持运行
  • 如果程序出现 panic 异常,可以通过 defer 和 recover 实现 panic 异常的捕获,让程序正常运行。

注意

  • defer 和 recover 必须要在 panic 之前被定义
  • panic 异常会随着函数的调用栈向外传递 A函数调用了B函数, B函数调用了C函数,如果在C函数中抛出了一个panic异常, 那么这个异常会一层一层的传递到B和A,也就是在B和A函数中也能捕获到这个异常
func TestExceptionRecover(t *testing.T) {
 /*
    1.程序不要随意被终止, 只要不是程序不能运行了, 就尽量让改程序继续保持运行
    2.在Go语言中如果panic异常, 那么可以通过defer和recover来实现panic异常的捕获, 让程序继续执行
    注意点:
    1.defer和recover必须在panic抛出异常之前定义
    2.panic异常会随着函数的调用栈向外传递
    例如: A函数调用了B函数, B函数调用了C函数
          如果在C函数中抛出了一个panic异常, 那么这个异常会一层一层的传递到B和A
          也就是在B和A函数中也能捕获到这个异常
 */
 defer func() {
  if err := recover(); err != nil {
   fmt.Println("recover 捕获到了异常", err)
  }
 }()
 res := div2(10, 0)
 fmt.Println(res)
}
// 除法运算
func div2(a, b int) (res int) {
 // 在当前函数中捕获
 //defer func() {
 // // defer无论所在的函数是正常结束,还是异常结束都会被执行
 // // recover可以捕获panic异常
 // if err := recover(); err != nil{
 //    fmt.Println("recover捕获到了", err)
 // }
 //}()
 if b == 0 {
  // 手动终止程序
  panic("除数不能为0")
 } else {
  res = a / b
 }
 // 无效
 //defer func() {
 // // defer无论所在的函数是正常结束,还是异常结束都会被执行
 // // recover可以捕获panic异常
 // if err := recover(); err != nil{
 //    fmt.Println(err)
 // }
 //}()
 return
}

运行结果:

=== RUN   TestExceptionRecover
recover 捕获到了异常 除数不能为0
--- PASS: TestExceptionRecover (0.00s)
PASS


捕获异常注意点


同一个函数中,多个 panic 异常,只要第一个会被捕获

func TestPanics(t *testing.T) {
 /*
    捕获异常注意点:
    1.同一个函数中, 多个panic异常, 只有第一个会被捕获
 */
 /*defer func() {
  if err := recover(); err != nil {
   fmt.Println(err) //异常1
  }
 }()
 panic("异常1")
 panic("异常2")
 panic("异常3")
 panic("异常4")*/
 panicfuc()
}
func panicfuc() {
 // 如果有异常写在defer中, 但是defer后面还有其它异常, 那么捕获到的是其它的异常
 // 如果其它异常是写在defer前面, 那么和同一个函数中, 多个panic异常, 只有第一个会被捕获
 defer func() {
  if err := recover(); err != nil {
   fmt.Println(err) // 异常B
  }
 }()
 defer func() {
  panic("异常B")
 }()
 panic("异常C")
}


运行结果


=== RUN   TestPanics
异常B
--- PASS: TestPanics (0.00s)
PASS
相关文章
|
6月前
|
Go 开发者
Go语言中的错误处理与异常机制:实践与最佳策略
【2月更文挑战第7天】Go语言以其独特的错误处理机制而闻名,它鼓励显式错误检查而不是依赖于异常。本文将探讨错误处理与异常机制在Go语言中的实际应用,并分享一些最佳实践,帮助开发者编写更加健壮和易于维护的Go代码。
一文搞懂Go语言错误处理【异常捕获、异常抛出】
一文搞懂Go语言错误处理【异常捕获、异常抛出】
一文搞懂Go语言错误处理【异常捕获、异常抛出】
|
存储 数据可视化 Go
记一次线上Go服务内存占用异常问题排查
记一次线上Go服务内存占用异常问题排查
488 0
记一次线上Go服务内存占用异常问题排查
|
Java Go C语言
【Go必知必会】错误和异常、CGO、fallthrough
在一个 switch 块内,每个 case 无需声明 break 来终止,如果想顺序执行使用fallthrough; 如果我们想强制执行满足条件case的后一个case,也可以通过设置fallthrough的方式:
155 0
【Go必知必会】错误和异常、CGO、fallthrough
|
消息中间件 Go API
一次Go应用上云后线上性能异常排查
先说结论:资源使用不合理导致机器性能浪费起因:线上某应用告警机器负载及资源占用异常,登陆机器查看进程vmstat发现idle比较低线上是一个Go的应用,而且已经开启了PProf,索性就利用该工具分析一下性能瓶颈在哪PProf如何使用不在本文赘述,经分析初步断定在`ReceiveMessage`这个接口该方法是阿里云的SDK三方包提供的,按道理三方包不会出问题通过代码分析出send函数本质是通过一个
一次Go应用上云后线上性能异常排查
|
Java Go API
慢聊Go之Go中的异常与错误|Go主题月
慢聊Go之Go中的异常与错误|Go主题月
178 0
go语言panic异常及recover拦截恢复初级
go语言panic异常及recover拦截恢复初级 Go语言为我们提供了专用于“拦截”运行时panic的内建函数——recover。它可以是当前的程序从运行时panic的状态中恢复并重新获得流程控制权。
2590 0
|
6天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2