首先强烈安利AI练中学,方便直观的看到运行结果,不需要自己去配置各类环境,对于初学者,浪费大量时间配置环境是一件很打消学习积极性的事情
由于Go语言的错误处理和Java的不太一样,所以我觉得这个基本特性还是比较有趣的。
1.Go语言错误处理的基本介绍
首先来看一个常见的错误处理模式
func main() {
conent,err:=ioutil.ReadFile("filepath")
if err !=nil{
//错误处理
}else {
fmt.Println(string(conent))
}
}
这类错误判断的代码十分常见的,大部分情况下都是nil,即没有错误,但是如果检查到不是nil,那么说明出现了问题。这是error的接口定义
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
实际上我们能够看到所谓错误实际上只是一个包按着Error()方法的结构体,并且只返回一个string来提示错误所在。所以在实际情况中并不能很好的满足我们错误处理的需求。所以我们往往使用errors库来增加error的功能,这也是实际工程的选择。
2.errors库的基本使用
错误的创建:
func New(message string) error
这里的message是错误对象中包含的信息,这是最基础的功能。在代码中只需要简单的调用即可,他会创建出一个新的错误对象供我们使用,这里的err也只是一个简单地实现了Go语言接口的对象。
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("error")
fmt.Println(err.Error()) // 打印“error"
}
错误的判断:
func Is(err, target error) bool
Is函数能够帮助我们判断一个错误是否属于某类错误,参数需要一个错误对象,以及一个想要判断的目标错误对象,返回值为一个bool值,相同则返回1,不同则返回0
package main
import (
"errors"
"fmt"
)
var (
ErrFileEmpty = errors.New("the text file is empty!")
)
func main() {
err := fmt.Errorf("%w: fileName=%s", ErrFileEmpty, "hello.txt")
if errors.Is(err, ErrFileEmpty) {
fmt.Println("Yes,it is")
} else {
fmt.Println(err)
}
}
首先定义了一个错误变量 ErrFileEmpty ,用于表示一个文件空白的错误情况,之后利用 fmt.Errorf 函数可以包装该错误,并且然后使用 errors.Is 判断 err 是否等于或包含 ErrFileEmpty。最后会返回一个true
错误断言:As 函数
errors.As 函数用于检查一个错误是否可以被断言为特定的错误类型,成功则将错误包含的值赋给这个特定的错误变量。
func As(err error, target any) bool
err 为当前错误。target 为目标错误,不能为空
package main
import (
"errors"
"fmt"
)
type ErrFileEmpty struct {
fileName string
}
func (e *ErrFileEmpty) Error() string {
return fmt.Sprintf("fileName=%s", e.fileName)
}
func main() {
var err = &ErrFileEmpty{fileName: "hello.txt"}
var err1 = &ErrFileEmpty{}
if errors.As(err, &err1) {
fmt.Println(err1.fileName) // hello.txt
}
}
这个函数与Is的区别主要在于,它在判断的同时会将错误内部的值也赋值给目标错误。,例如我们这里创建了一个ErrFileEmpty的错误err,并且给他赋予了初值。之后创建了一个空白的ErrFileEmpty错误。最后就可以使用As函数对其进行判断和赋值,因为两者是相同的错误,所以最后err1的fileName值就变成为hello.txt,证明赋值成功了。
包装错误:Join 函数
errors.Join 用于包装特定的 errs 并返回一个新的错误对象。需要注意的是 errors.Join 在包装 error 的过程中,会忽略 nil error。
func Join(errs ...error) error
errs 为所给定的错误集,之后返回一个 error 接口类型的经过包装的对象
package main
import (
"errors"
"fmt"
)
func main() {
err1 := errors.New("errorOne")
err2 := errors.New("errorTwo")
err := errors.Join(err1, err2)
fmt.Println(err)
fmt.Println(errors.Is(err, err1)) // true
fmt.Println(errors.Is(err, err2)) // true
程序的运行结果为:
errorOne
errorTWO //前面两行都属于err的部分
true
true
获取原始错误:Unwrap 函数
errors.Unwrap 函数主要就是解包装,跟上面Join函数正相反
func Unwrap(err error) error
err 为所给定的错误,之后返回一个 error 类型的解包后的对象,注意此时只解一个包
package main
import (
"errors"
"fmt"
)
var (
ErrFileEmpty = errors.New("file is empty")
)
func main() {
err := fmt.Errorf("%w: fileName=%s", ErrFileEmpty, "hello.txt")
fmt.Println(err)
fmt.Println(errors.Unwrap(err))
}
运行结果
file is empty,fileName=hello.txt
file is empty