Go语言中的异常和错误处理简介

女主宣言

异常和错误处理在保证程序的鲁棒性方面起到了至关重要的作用。C++、Java、Python中的异常和错误处理都是比较类似的,可以用try-catch逻辑操作,但是Go中的异常处理却有别于以上三种语言。接下来就跟随作者一起看下在Go语言中,异常和错误是如何处理的吧。

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

1

异常处理

在异常处理方面,Go语言不像其他语言,使用try..catch.. finall..., 而使用defer, panic, recover,将异常和控制流程区分开。即通过panic抛出异常,然后在defer中,通过recover捕获这个异常,最后处理。

先来看一个案例吧,如下:

func main() {
   //立即执行函数
   defer func(){ //   声明defer,
      fmt.Println("----调用 defer1 start----")
      if err:=recover(); err!=nil{
         fmt.Println(err) // 这里的err其实就是panic传入的内容
      }
      fmt.Println("----调用 defer1 end----")
   }()
 
   defer func(){ //   声明defer,
      fmt.Println("----调用 defer2 start----")
      if err:=recover(); err!=nil{
         fmt.Println(err) // 这里的err其实就是panic传入的内容
      }
      fmt.Println("----调用 defe2r end----")
   }()
 
   panic("测试")
}

执行结果:

defer的思想类似于C++中的析构函数,就是在程序结束前执行的语句,defer后面可以是一个立即执行函数,也可以是一条语句。

defer可以多次,这样形成一个defer栈,后添加的会先被调用。

panic 是用来表示非常严重的不可恢复的错误的。在Go语言中这是一个内置函数,接收一个interface{}类型的值(也就是任何值了)作为参数。

panic的作用就像我们平常接触的异常,所以,调用panic会让程序不会继续往下执行(除非recover)。

recover捕获异常后的异常,不能再次被recover捕获。

2

错误处理

Go标准包提供的错误处理功能,error是个interface,如下:

type error interface {
    Error() string
}

且go提供了errorString结构体,其则实现了error接口,如下:

// errorString is a trivial implementation of error.
type errorString struct {
   s string
}
 
func (e *errorString) Error() string {
   return e.s
}

在errors包中,还提供了New函数,来实例化errorString,如下:

// New returns an error that formats as the given text.
func New(text string) error {
   return &errorString{text}
}

于是,在定义函数的时候,我们就可以如下:

func add(args ... int) (int, error){
   var sum int
   if len(args) == 0 {
      return 0, errors.New("参数为空")
   }
   for _ ,arg := range args {
      sum += arg
   }
   return sum, nil
}

调用:

//立即执行函数
sum , err := add()
if err != nil {
   fmt.Println(err.Error())
} else {
   fmt.Println(sum)
}

输出:

当然,我们也可以自己去实现error接口,如下:

type myError struct {
   curFile     string
   code        int
   description string
}
//实现Error方法,那么myError就实现了error接口
func (e *myError) Error() string {
   return e.description
}

然后在函数中,使用我们自己定义的错误,如下:

func add(args ... int) (int, error) {
   var sum int
   if len(args) == 0 {
      return 0, &myError{curFile: "test.go", code: -1, description: "参数不能为空哦!"}
   }
   for _, arg := range args {
      sum += arg
   }
   return sum, nil
}

3

案例

案例1

下面程序的输出:

package main
 
import (
   "fmt"
)
 
func main() {
   doTest()
}
 
func doTest() {
   defer func() {
      panic("报错2")
   }()
 
   defer func() {
      panic("报错1")
   }()
 
   panic("报错3")
}

解析:defer可以多次,这样形成一个defer栈,后添加的会先被调用,所以输出“报错1”应该在“报错2”之前,且defer有点类似析构函数,所以输出“报错3”在“报错1”之前。

上面程序输出如下:

案例2

下面程序的输出:

package main
 
import (
   "fmt"
)
 
func main() {
   doTest()
   fmt.Println("main捕获到错误:", recover())
}
 
func doTest() {
   defer func() {
      fmt.Println("1捕获到错误:", recover())
   }()
   fmt.Println("2捕获到错误:", recover())
   panic("报错3")
}

分析:recover 只有在 defer 调用的函数中才有效,否则当panic时,recover无法捕获到panic,变回输出nil。

上面程序输出如下:

360云计算

由360云平台团队打造的技术分享公众号,内容涉及数据库、大数据、微服务、容器、AIOps、IoT等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值