错误处理
Golang中的错误类型
程序执行的过程中会发生的异常情况称为错误。比如打开一个文件系统不存在的文件就会发生错误。
Golang中有个专门用来表示错误的接口类型:error
。
跟int
、float64
等其他数据类型类似,error
类型的值也可以拿来赋值给变量,传参给函数,或者作为函数返回值。
举例
我们举个例子,尝试打开一个系统不存在的文件。
这里我们尝试打开路径为/test.txt
的文件。os.Open
函数的签名如下:
如果文件打开成功,则Open
函数返回值file
为该文件的指针,同时返回值err
为nil
。如果读取文件发生异常,比如文件不存在,则返回值err
不为nil
。
在Golang中,如果一个函数/方法会返回错误,一般都是作为最后一个返回值,这里的Open
函数返回的错误就是位于第二个位置,也就是最后一个位置。
通常情况下我们都是将函数返回的error
字段跟nil
比较。如果是nil
,则表示无错误,否则表示有错误发生。
前面的程序我们就是将error
跟nil
比较,来判断是否正常打开文件。该程序执行结果为:
很明显,该错误信息表示文件/test.txt
不存在(我的机器确实不存在该文件,你的机器应该也不会凑巧存在该文件吧)。
error
接口类型
error
接口类型Golang中error
是一个接口类型,定义如下:
该接口仅包含一个方法Error() string
,该方法用来表示错误信息。任何实现了该接口的类型都是错误类型。当我们通过fmt.Println
打印一个错误类型的变量时,其实就是调用其Error() string
方法获取错误信息并打印。
获取更多错误信息
Golang中的error
是一个接口类型,现在我们看下如果从error
变量中提取更多错误相关的信息。
前面的例子中我们打印出了错误的描述信息,但是如果我们想获取发生错误的文件路径怎么实现呢?
这肯定是能够实现的,比如我们打印出的错误信息里面就有这个信息,可以解析出来。但是直接从错误文本信息中解析文件路径非常不明智,我们应该寻找更加正规靠谱的方法。
1.断言error具体类型并通过其属性获取信息
我们看下Open函数的官方文档会发现,该函数返回的错误字段的类型为*PathError
。PathError
是一个结构体类型,该类型实现了Error() string
方法,实现了error
接口,因此属于error
类型。
这几行源码可以参考https://golang.org/src/os/error.go?s=653:716#L11。
从Error()
函数的实现我们就能理解前面的输出了:
结构体类型PathError
的属性Path
就是用来表示文件路径的,因此我们可以读取该字段来获取文件路径。
这里我们通过类型断言来获取了error
接口内部的具体值。接着我们通过err.Path
来获取文件路径。该程序输出为:
2.断言error具体类型并通过其方法获取信息
当我们断言出error
内部的具体类型后,不仅可以通过其属性获取更多有用信息,还可以调用其方法来获取信息。我们通过例子来理解下。在Golang标准库中,结构体类型DNSError的定义如下:
该结构体类型有两个方法Timeout() bool
和Temporary() bool
用来表示具体错误原因是超时还是暂时解析失败。下面我们实现一个例子,来断言*DNSError
类型,如果断言成功则调用其方法来判断错误原因。
这里我们尝试获取域名golangbot123.com
的ip地址,由于该域名是不存在的,因此会报域名解析错误,即net.DNSError
类型的错误。我们断言该类型错误,然后调用该类型错误上的方法来判断具体错误原因。该程序运行结果如下:
3.直接判断相等
第三种获取更多错误相关信息的方法就是直接将错误字段跟某个error
类型的已有变量做比较。我们还是通过例子来了解下。
filepath
包中有个函数Glob用来返回跟某个正则匹配的文件目录。如果正则写的格式有问题会返回一个错误变量ErrBadPattern
。ErrBadPattern
在filepath
包中定义为:
这里errors.New()
用来创建一个error
类型的变量。由于这里定义的ErrBadPattern
是大写开头的,因此属于导出型变量,我们能够直接在包外访问到该变量。下面我们通过例子来判断下错误是否是ErrBadPattern
。
这里我们传给Glob
的参数是[
,格式是错误的(具体为什么是错误的可以去看Glob相关文档)。然后我们直接将返回的错误字段跟变量filepath.ErrBadPattern
去比较是否相等,如果相等则证明确实是该错误。该程序执行结果如下:
Golang中基本都是基于这3种方式来提供更多错误相关的细节信息。我们下一节也会基于这几种方式来自定义错误类型。
不要忽略错误
注意,永远不要忽略错误字段。比如下面的程序就忽略了filepath.Glob()
返回的错误字段。
由于入参[
是格式错误的,因此会返回错误字段,但是我们通过_
将该错误忽略了。该程序输出为matched files []
,表面上看起来是未匹配到任何字段,其实是发生了错误。因此我们在Golang编程中永远不要随意的忽略一个错误。
Last updated
Was this helpful?