如何用GO语言实现高效的异常处理机制?
摘要:在开发中, 处理异常是很重要的, 考虑各种错误情况并且提出对应的解决办法是保证不出大BUG的重要之处. error in go GO语言的异常是很简单的, 只需要实现Error函数接口即可 func (e ErrA) Error() str
在开发中, 处理异常是很重要的, 考虑各种错误情况并且提出对应的解决办法是保证不出大BUG的重要之处.
error in go
GO语言的异常是很简单的, 只需要实现Error函数接口即可
func (e ErrA) Error() string {
return "ErrA"
}
过于简单的实现, 和C一样
errors
这是GO的一个库, 专门用来处理异常
Go语言的标准库一般会在后面加一个s代表是处理这种类型的标准库, 例如strings
异常处理
error类别判断
类型断言实现类别判断
Go语言提供了类型断言的方式, 针对接口, 可以实现不同类型之间的相互转换
这就是为什么errA需要是error类型, 因为是接口类型才能转换
var errA error = ErrA{}
var errB error = ErrB{}
fmt.Println(errA.Error())
fmt.Println(errB.Error())
if e, ok := errA.(ErrB); ok {
fmt.Println(e)
fmt.Println("found ErrB")
} else {
fmt.Println("not found ErrB")
}
这个简单好用, 如果需要嵌套的异常处理, 那么应该选择使用这个.
当然可以使用switch语句针对多种错误类型进行处理, 针对多个类型的时候使用这个方式可以更好的处理
func main() {
var errA error = ErrA{}
var errB error = ErrB{wrappedErr: errA}
for err := errB; err != nil; err = errors.Unwrap(err) {
fmt.Println(err)
switch err.(type) {
case ErrA:
fmt.Println("ErrA")
case ErrB:
fmt.Println("ErrB")
default:
fmt.Println("default")
}
fmt.Println()
}
}
上述代码是使用switch配合类型断言来处理异常
errors函数类别判断
通过errors.Is或者errors.As函数实现类别的判断
Go语言官方提供的异常处理, 也只是简单的封装.
这个函数的本质是检查这个error是否包含某个error(一个error可以包含多个error, 嵌套error)
var errA error = ErrA{}
var errB error = ErrB{}
fmt.Println(errA.Error())
fmt.Println(errB.Error())
if errors.Is(errA, errB) {
fmt.Println("errA is errB")
} else {
fmt.Println("errA is not errB")
}
使用这个函数让代码看起来十分的简洁
使用errors提供的函数在处理嵌套的error的时候可能存在问题, 我们在下面讨论
嵌套error
有些时候我们需要把error一层一层wrap起来然后向上抛出异常进行处理. 像是多层的Throw错误.
errors库提供了Unwrap函数, 如果error实现了这个接口, 那么就可以实现error嵌套
package main
import (
"errors"
"fmt"
)
type ErrA struct {
wrappedErr error
}
func (e ErrA) Error() string {
return fmt.Sprintf("ErrA -> %v", e.wrappedErr)
}
func (e ErrA) Unwrap() error {
return e.wrappedErr
}
type ErrB struct {
wrappedErr error
}
func (e ErrB) Error() string {
return fmt.Sprintf("ErrB -> %v", e.wrappedErr)
}
func (e ErrB) Unwrap() error {
return e.wrappedErr
}
func main() {
errA := ErrA{}
errB := ErrB{}
fmt.Println(errA.Error())
fmt
