go语言为了更加简洁优雅,没有类似java的try...catch...这种写法,因为try...catch在某些情况下会嵌套使用,造成代码运行后不知道哪里就跑到了异常处理的代码里。
但是也有相应的异常处理机制。
需要记住的关键词有个,error,defer,panic,recover。
1 error
error类似java中的Exception类型,不同的是Exception必须搭配throw和catch使用。Go语言中的error类型实际上是抽象了Error()方法的error接口:
type error interface {
Error() string
}
Go语言使用该接口进行标准的错误处理。对于大多数函数,如果要返回错误,大致上都可以定义为如下模式,将error作为多种返回值中的最后一个:
//定义函数
func Foo(param int)(n int, err error) {
// ...
}
//调用函数
n, err := Foo(0)
if err != nil {
// 错误处理
} else {
// 使用返回值n
}
2 defer
defer相当于java中的finally,c中的析构函数。不管有没有发生异常的情况下,defer定义的函数都会被执行。一般用来进行资源回收等操作,防止程序员忘记这些操作。
defer语句的用法有两个优点:
1.让设计者永远也不会忘记关闭文件,有时当函数返回时常常忘记释放打开的资源变量。
2.将关闭和打开靠在一起,程序的意图变得清晰很多。
3 panic-recover运行时异常处理机制
Go语言中没有Java中那种try-catch-finally结构化异常处理机制,而使用panic()函数引发错误(等同于throw/raise),然后在defer语句中调用recover()函数捕获错误,这就是Go语言的异常恢复机制——panic-recover机制。
下面来看一段代码来综合运用这4个关键词。
package main
import (
"fmt"
)
//自定义错误类型
type ArithmeticError struct {
error
}
//重写Error()方法
func (this *ArithmeticError) Error() string {
return "自定义的error,error名称为算数不合法"
}
//定义除法运算函数***
func Devide(num1, num2 int) int {
if num2 == 0 {
panic(&ArithmeticError{}) //当然也可以使用ArithmeticError{}同时recover等到ArithmeticError类型
} else {
return num1 / num2
}
}
func main() {
var a, b int
fmt.Scanf("%d %d", &a, &b)
defer func() {
if r := recover(); r != nil {
fmt.Printf("panic的内容%v\n", r)
if _, ok := r.(error); ok {
fmt.Println("panic--recover()得到的是error类型")
}
if _, ok := r.(*ArithmeticError); ok {
fmt.Println("panic--recover()得到的是ArithmeticError类型")
}
if _, ok := r.(string); ok {
fmt.Println("panic--recover()得到的是string类型")
}
}
}()
rs := Devide(a, b)
fmt.Println("结果是:", rs)
}
总结:
- go中error相当于java中的Exception,defer相当于java中的finally,panic相当于java中的throw,panic和recover一起使用相当于java中的try...catch...。