错误处理
在java中我们需要进行异常复杂的异常处理,但是在golang中可以知道是哪个函数返回了错误然后再对相应错了的函数改改bug。在go语言中不再和java一样有结构化异常,go语言通过panic抛出异常,用recover来捕获异常。
获取错误信息
在go中通常使异常跟随着函数的返回值而返回,如下所示。
func Demo() (T, error)
并在语句中设置一个变量来接受错误并判断是否发生错误
_,err := Demo()
if err != nil {
fmt.Println("error")
return
}
同时也能自己自定义异常信息
func Demo() (T, error) {
return 0, errors.New("error info")
}
若想要获得更多关于异常的信息的话,需要实现error中的Error方法,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
}
只需要在结构体中实现上面的方法,随后再打印出具体的错误内容即可
type errorInfo interface {
s string
}
//绑定
func (e *errorInfo) Error() string {
return e.s;//返回错误信息
}
defer
在正常编写业务时,有些比较粗心的程序员会建立数据库连接或者开启其他资源,在不再使用这些资源之后会忘记关闭相关连接。在java中可以通过实现autoclose接口进行关闭,不过这样的操作需要在开启资源时使用try catch捕获相关资源占用内存资源,在go语言中提供了defer关键字,在程序执行完毕之后会从下往上执行defer修饰的语句。现有下代码
fmt.Println("hello java")
defer fmt.Println("hello world")
defer fmt.Println("hello go")
//最终输出为
/*
hello java
hello go
hello world
*/
由于defer的特性它可以用于以下操作
- 并发时释放共享资源锁
- 延迟释放文件句柄
- 延迟关闭
tcp连接- 延迟关闭数据库连接
panic
在程序运行的过程中假如检测到了某些异常可以使用panic(宕机)来手动中止主线程运行并且打印出相关的日志信息
defer fmt.Println("关闭文件句柄")
panic("人工创建的运行时异常")
recover
出现 panic 以后程序会终止运行,所以我们应该在测试阶段发现这些问题,然后进行规避,但是如果在程序中产生不可预料的异常(比如在线的web或者rpc服务一般框架层),即使出现问题(一般是遇到不可预料的异常数据)也不应该直接崩溃,应该打印异常日志,关闭资源,跳过异常数据部分,然后继续运行下去,不然线上容易出现大面积血崩。
然后再借助运维监控系统对日志的监控,发送告警给运维、开发人员,进行紧急修复。
总结
- 创建一个异常
errors.New("字符串")- 打印异常信息
err.Error()- 调用
panic后,当前函数从调用点直接退出recover函数只有在defer代码块中才会有效果recover可以放在最外层函数,做统一异常处理。