首先说一下: 错误指的是可能出现问题的地方出现了问题。如打开件失败,这种情况在意料之中 。异常指的是不应该出现问题的地方出现了问题。如引用了空指针,这种情况在意料之外

Go
errorpanic

1. panic

Go的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起painc异常。

一般而言,当panic异常发生时,程序会中断运行,并立即执行在该goroutine(可以先理解成线程)中被延迟的函数(defer 机制)。随后,程序崩溃并输出日志信息。日志信息包括panic value和函数调用的堆栈跟踪信息。panic value通常是某种错误信息。对于每个goroutine,日志信息中都会有与之相对的,发生panic时的函数调用堆栈跟踪信息。通常,我们不需要再次运行程序去定位问题,日志信息已经提供了足够的诊断依据。因此,在我们填写问题报告时,一般会将panic异常和日志信息一并记录。不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常;panic函数接受任何值作为参数。当某些不应该发生的场景发生时,我们就应该调用panic。虽然Go的panic机制类似于其他语言的异常,但panic的适用场景有一些不同。由于panic会引起程序的崩溃,因此panic一般用于严重错误,如程序内部的逻辑不一致。

panicGopanicerrorGoGoroutine

总结来说:

panic是一个严重错误机制,它会导致程序终止,并依次逆序执行 panic 所在函数可能存在的 defer 函数列表,然后返回该函数的调用方。recover 内置函数可用于捕获 panic,重新恢复程序正常执行流程,但是 recover 函数只有在 defer 内部使用才有效

panic()panic()panic()defer

2. recover

recoverGogoroutine
recovernil

注意:利用recover处理panic指令,defer必须在panic之前声明,否则当panic时,recover无法捕获到panic.

Gopanicrecovertry/catch

panic 和 recover 的关系

panic 和 recover 的组合有如下特性:

有 panic 没 recover ,程序宕机。
有 panic 也有 recover ,程序不会宕机,执行完对应的 defer 后,从宕机点退出当前函数后继续执行。
注意:在 panic 触发的 defer 函数内,可以继续调用 panic ,进一步将错误外抛,直到程序整体崩溃。如果想在捕获错误时设置当前函数的返回值,可以对返回值使用命名返回值方式直接进行设置。

示例:

package main

func test() {
	defer func() {
		if err := recover(); err != nil { // recover 捕获错误。
			println(err.(string)) // 将 interface{} 转型为具体类型。
		}
	}()
	panic("panic error!")	// panic 抛出错误
}
func main() {
	test()
}

3. error

go中的错误处理,是通过返回值的形式来出来,要么你忽略,要么你处理(处理也可以是继续返回给调用者),对于golang这种设计方式,我们会在代码中写大量的if判断,以便做出决定。

对于err如果是nil就代表没有错误,如果不是nil就代表程序出问题了,需要对错误进行处理了。

示例:

func main() {
	conent,err:=ioutil.ReadFile("filepath")
	if err !=nil{
		//错误处理
	}else {
		fmt.Println(string(conent))
	}
}

此外,error类型是go语言的一种内置类型,使用的时候不用特定去import,他本质上是一个接口,

 type error interface{
  Error() string //Error()是每一个订制的error对象需要填充的错误消息,可以理解成是一个字段Error
}