Go——错误处理(error)

1、error

Go语言内置错误接口类型error。任何类型只要实现Error()string方法,都可以传递error接口类型变量。Go语言典型的错误处理方式是将erorr作为函数最后一个返回值。在调用函数时,通过检测其返回的eror值是否为nil来进行错误处理。

//$GOROOT/src/go/src/builtin/builtin.go

type error interface {
	Error() string
}

Go语言标准库提供的两个函数返回实现了eror接口的具体类型实例,一般的错误可以使用这两个函数进行封装。遇到复杂的错误,用户也可以自定义错误类型,只要其实现eror接口即可。例如:

//http://golang.org/src/pkg/fmt/print.go

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorf(format string, a ...interface{}) error {
	return errors.New(Sprintf(format, a...))
}

//http://golang.org/src/pkg/errors/errors.go

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

错误处理的最佳实践:

  • 在多个返回值的函数中,error通常作为函数最后一个返回值。
  • 如果一个函数返回error类型变量,则先用f语句处理error!=nil的异常场景,正常逻辑放到f语句块的后面,保持代码平坦。
  • defer语句应该放到err判断的后面,不然有可能产生panic。
  • 在错误逐级向上传递的过程中,错误信息应该不断地丰富和完善,而不是简单地抛出下层调用的错误。这在错误日志分析时非常有用和友好。

2、错误和异常

异常和错误在现代编程语言中是一对使用混乱的词语,下面将错误和异常做一个区分。

  • 广义上的错误:发生非期望的行为。
  • 狭义的错误:发生非期望的已知行为,这里的已知是指错误的类型是预料并定义好的。
  • 异常:发生非期待的未知行为。这里的未知是指错误的类型不在预先定义的范围内。异常又被称为未捕获的错误(untrapped error)。程序在执行时发生未预先定义的错误,程序编译器和运行时都没有及时将其捕获处理。而是由操作系统进行异常处理,比如C语言程序里面经常出现的Segmentation Fault(段异常错误),这个就属于异常范畴。

在这里插入图片描述

Go是一门类型安全的语言,其运行时不会出现这种编译器和运行时都无法捕获的错误,也就是说,不会出现untrapped error,所以从这个角度来说,Go语言不存在所谓的异常,出现的“异常”全是错误。

Go程序需要处理的这些错误可以分为两类:

  • 一类是运行时错误(runtime errors),此类错误语言的运行时能够捕获,并采取措施——隐式或显式地抛出panic。
  • 一类是程序逻辑错误:程序执行结果不符合预期,但不会引发运行时错误。

对于运行时错误,程序员无法完全避免其发生,只能尽量减少其发生的概率,并在不影响程序主功能的分支流程上“recover”这些panic,避免其因为一个panic引发整个程序的崩溃。

go对于错误提供了两种处理机制:

  1. 通过函数返回错误类型的值来处理错误。
  2. 通过panic打印程序调用栈,终止程序执行来处理错误。

所以对错误的处理也有两种方法,一种是通过返回一个错误类型值来处理错误,另一种是直接调用panic抛出错误,退出程序。

Go是静态强类型语言,程序的大部分错误是可以在编译器检测到的,但是有些错误行为需要在运行期才能检测出来。此种错误行为将导致程序异常退出。其表现出的行为就和直接调用panic一样:打印出函数调用栈信息,并且终止程序执行。

在实际的编程中,error和panic的使用应该遵循如下三条原则:

  1. 程序局部代码的执行结果不符合预期,但此种行为不是运行时错误范围内预定义的错误,此种非期望的行为不会导致程序无法提供服务,此类场景应该使用函数返回error类型变量进行错误处理。
  2. 程序执行过程中发生错误,且该种错误是运行时错误范围内预定义的错误,此时Go语言默认的隐式处理动作就是调用panic,如果此种panic发生在程序的分支流程不影响主要功能,则可以在发生panic的程序分支上游处使用recover进行捕获,避免引发整个程序的崩溃。
  3. 程序局部代码执行结果不符合预期,此种行为虽然不是运行时错误范围内预定义的错误,但此种非期望的行为会导致程序无法继续提供服务,此类场景在代码中应该主动调用panic,终止程序的执行。

进一步浓缩为两条规则:

  1. 程序发生的错误导致程序不能容错继续执行,此时程序应该主动调用panic或由运行时抛出panic。

  2. 程序虽然发生错误,但是程序能够容错继续执行,此时应该使用错误返回值的方式处理错误,或者在可能发生运行时错误的非关键分支上使用recover捕获panic。

Go的整个错误处理过程如下图:
在这里插入图片描述

G0程序的有些错误是在运行时进行检测的,运行期的错误检测包括空指针、数组越界等。如果运行时发生错误,则程序出于安全设计会自动产生panic。另外,程序在编码阶段通过主动调用panic来进行快速报错,这也是一种有效的调试手段。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值