一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
错误
错误是可预期的,并不是非常严重,不会影响程序的运行
func main() {
i, err := strconv.Atoi("A")
if err != nil {
fmt.Println(err)
} else {
fmt.Println(i)
}
}
type error interface {
Error() string
}
err工厂函数
func main() {
sum, err := add(-1, 2)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(sum)
}
}
type error interface {
Error() string
}
func add(a, b int) (int, error) {
if a < 0 || b < 0 {
return 0, errors.New("a或者b不能为负数")
} else {
return a + b, nil
}
}
以上的程序是一个经典的应用,比如输入年龄的时候,年龄不能为负。这就需要错误的判断。当a或者b小于0的时候,输出a或者b不能为负数。
自定义err
上面的例子中,无论是普通err还是err工厂函数中,遇到错误返回错误的时候只能返回一个字符串。为了实现携带跟多的信息,需要自定义err。
type commonError struct {
errorCode int
errorMsg string
}
通过定义带有更多信息的结构体,实现返回时携带更多信息。
return 0, &commonError{
errorCode: 1,
errorMsg: "a或者b不能为负数",
}
通过这种方式返回,可以自定义错误码和错误信息。
Error Wrapping
但是当错误进行嵌套,也就是基于上一个错误进行下一个错误的时候,err就不是很适用了。(可以在err结构体中嵌套err信息,但是十分繁琐)
e := error.New("原来的错误e")
w := fmt.Errorf("Wrap了一个错误:%w",e)
fmt.Println(w)
fmt.Println(errors.Unwrap(w))
Go语言通过fmt.Errorf加上%w的方式包裹嵌套另一个error。通过errors.Unwrap可以获取被嵌套的error。
errors.Is函数
func Is(err, target error) bool
errors.Is函数用来判断错误是否相同,如果err和target是同一个返回true,如果err是一个wrapping error,target包含在这个嵌套err中也返回true。
errors.As函数
因为不知道错误被嵌套了几层,所以err断言不能使用了,于是Go提供errors.As函数进行嵌套error的断言。
Deffered函数
defer函数可以保证文件关闭后一定会被执行,不管自定义的函数出现异常还是错误。(适用于文件打开后最后关闭以节约资源)
func ReadFile(filename string)([]byte,error) {
f,err:=os.Open(filename)
if err != nil {
return nil,err
}
defer f.Close()
return readAll(f,n)
}
Panic异常
Go语言是一种静态强类型语言,但是有些问题只能在运行时检查,这类运行时问题会引起panic异常。我们自己也可以在必要的时候抛出panic异常。