学习资料来自
GitHub - unknwon/the-way-to-go_ZH_CN: 《The Way to Go》中文译本,中文正式名《Go 入门指南》
错误处理
1、错误处理机制
1)普通错误:将错误对象作为函数或者方法的最后一个返回值,返回nil表示没有错误发生(不需要错误检测时 _ 代替,需要时使用 err),以下展示普通错误的一些构建方
- errors 包(注意:错误信息会以Error:开头,注重语法的话,错误信息记得小写开头)
// errors包预先定义 error 接口
type error interface {
Error() string
}
// 当需要新的错误类型,即可使用 errors 包
err := errors.New("math - square root of negative number")
- 自定义错误类型,可返回自己希望的错误信息
// 路径错误,返回操作以及文件位置
type PathError struct {
Op string // 操作
Path string // 文件的位置
Err error
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": "+ e.Err.Error()
}
- syscall包 :低阶外部包,用来提供系统基本调用的原始接口。返回封装整数类型错误码的 syscall.Errno,syscall.Errno 实现了 Error 接口。os包基于syscall错误提供标准错误
var (
EPERM Error = Errno(syscall.EPERM)
ENOENT Error = Errno(syscall.ENOENT)
ESRCH Error = Errno(syscall.ESRCH)
EINTR Error = Errno(syscall.EINTR)
EIO Error = Errno(syscall.EIO)
...
)
- 借助 fmt 创建
if f < 0 {
return 0, fmt.Errorf("math: square root of negative number %g", f)
}
异常处理
1、运行时异常:程序运行中发生错误(类似数组下标越界),触发运行时panic,抛出接口值 runtime.Error(包含 RuntimeError() 用于区别普通错误)
2、panic:所测试的代码出现错误且严苛不可恢复,程序不能继续运行,使用 panic 产生终止程序的错误
1)panic 函数 :终止当前函数,可接受任意类型参数(常为字符串)
3、发送 panic 异常 —》终止当前程序 —》defer语句执行+控制权交还panic函数调用者 —》以此类推函数栈逐渐向上冒泡(每一层都执行defer后弹出)到顶层 —》栈顶程序崩溃
4、从panic恢复(recover) :阻止3中的崩溃过程
1)recover 只能在 defer 中使用,程序正常执行时,recover 返回 nil
defer func() {
log.Println("done")
// Println executes normally even if there is a panic
if err := recover(); err != nil {
log.Printf("run time panic: %v", err)
}
}()
5、自定义包中的错误
1)在包内部,应该从 panic 中进行 recover。
2)跨包的问题,在问题出现的包使用 panic 和 recover,在 recover 中构建错误信息返回,而不是继续向上 panic。
6、闭包处理(优雅起来!!!!):美丽的代价就是函数签名要一致
func errorHandler(fn fType1) fType1 {
return func(a type1, b type2) {
defer func() {
if err, ok := recover().(error); ok {
log.Printf("run time panic: %v", err)
}
}()
fn(a, b)
}
}
总:panic 会导致栈被展开直到 defer 修饰的 recover() 被调用或者程序终止。