GO语言错误处理

没有结构化异常,使⽤用 panic 抛出错误,recover 捕获错误。
func test() {
  defer func() {
    if err := recover(); err != nil {
      println(err.(string)) // 将 interface{} 转型为具体类型。
    }
  }()
  panic("panic error!")
}
由于 panic、recover 参数类型为 interface{},因此可抛出任何类型对象。
func panic(v interface{})
func recover() interface{}
延迟调⽤用中引发的错误,可被后续延迟调⽤用捕获,但仅最后⼀一个错误可被捕获。
func test() {
  defer func() {
    fmt.Println(recover())
  }()
  defer func() {
    panic("defer panic")
  }()
  panic("test panic")
}
func main() {
  test()
}
输出:
defer panic
捕获函数 recover 只有在延迟调⽤用内直接调⽤用才会终⽌止错误,否则总是返回 nil。任何未
捕获的错误都会沿调⽤用堆栈向外传递。
func test() {
  defer recover() // ⽆无效!
  defer fmt.Println(recover()) // ⽆无效!
  defer func() {
    func() {
      println("defer inner")
      recover() // ⽆无效!
    }()
  }()
  panic("test panic")
}
func main() {
  test()
}
输出:
defer inner
<nil>
panic: test panic
使⽤用延迟匿名函数或下⾯面这样都是有效的。
func except() {
  recover()
}
func test() {
  defer except()
  panic("test panic")
}
如果需要保护代码⽚片段,可将代码块重构成匿名函数,如此可确保后续代码被执⾏行。
func test(x, y int) {
  var z int
  func() {
    defer func() {
      if recover() != nil { z = 0 }
    }()
  z = x / y
  return
  }()
  println("x / y =", z)
}
除⽤用 panic 引发中断性错误外,还可返回 error 类型错误对象来表⽰示函数调⽤用状态。
type error interface {
  Error() string
}
标准库 errors.New 和 fmt.Errorf 函数⽤用于创建实现 error 接⼝口的错误对象。通过判断
错误对象实例来确定具体错误类型。
var ErrDivByZero = errors.New("division by zero")
func div(x, y int) (int, error) {
  if y == 0 { return 0, ErrDivByZero }
  return x / y, nil
}
func main() {
  switch z, err := div(10, 0); err {
    case nil:
      println(z)
    case ErrDivByZero:
      panic(err)
  }
}
如何区别使⽤用 panic 和 error 两种⽅方式?惯例是:导致关键流程出现不可修复性错误的
使⽤用 panic,其他使⽤用 error。

posted @ 2017-02-27 09:43  ruizhang3  阅读(593)  评论(0编辑  收藏  举报