Go 错误处理

一:error接口

Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:

  type error interface {

    Error() string

  }

  使用例子如下

  func Add(a,b int) error{

    if a>0 {

      err:=error.New("我的错误信息")

      return err

    }

    return nil

  }

  实现自定义的error类型

  type PathError struct{ //1:定义一个struct == C# class

    Err error        //2:定义一个error类型的成员

    Path string       

  }

  如何实现将PathError的类型是error类型呢?这里有一个接口的概念 ,后续的会介绍到

  func (this *PathError) Error() string{    //3:这边的Error等价与 C#中的 class ->method 感觉要是能够给Error写在struct中就更好了

    return "我的错误信息"          //4:因为这边的PathError 有个一名称为 Error()的方法 代表了这个自定义类型实现了error 接口,后面我们就可以认为

                        //PathError类型实现了error接口了,我们就可以将Path传递到error类型

  }

  func myExampleError(aa string) error{

    return &PathError{"stat", nil}

  }

 二: defer关键字

 提到这个关键字,我们可以想一下C#中连接数据库的时候使用

  SqlConnect conn=new SqlConnect();

  conn.open()

  /*代码段*/

  conn.close()

  其中conn在开启后必须等待做完很多操作后才能够将conn关闭 ,这个操作经常会忘记,或者中间错误也会造成conn无法关闭的问题

  后面为了解决这个问题提出有using(SqlConnect conn=new SqlConnect())来实现自动释放conn接口

  GO语言中的defer就等价与它

  使用方法

  file.open()

  defer file.close() 这边就是开启一个资源后,直接将该资源释放 ,而释放的过程实际上是在当前这个函数关闭后才执行的,所以我们开放

  一个资源后要紧记,立马使用defer释放,这样就可以避免资源无法释放的问题了

  注意:一个函数中可以存在多个defer语句,因此需要注意的是,defer语句的调用是遵照先进后出的原则,即最后一个defer语句将最先被执行

三:panic()和recover()

  func panic(interface{})

  func recover() interface{}

  当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误处理流程。

  

  recover()函数用于终止错误处理流程。一般情况下,recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字),会导致该goroutine所属的进程打印异常信息后直接退出。以下为一个常见的场景。

我们对于foo()函数的执行要么心里没底感觉可能会触发错误处理,或者自己在其中明确加入了按特定条件触发错误处理的语句,那么可以用如下方式在调用代码中截取recover():

  defer func() {

    if r := recover(); r != nil {

      log.Printf("Runtime error caught: %v", r)

    }

  }()

  foo()

上面的两个函数我理解的不是特别深,等待后续的继续学习。