在上篇分析singleflight的相关资料中,看到有文章说“doCall方法巧妙的使用两个defer来区分调用函数异常与系统异常”。今天查找资料,学习一下Go的异常处理机制,目前的大概印象,只知道一个关键字panic
。
在Go语言中,错误被认为是一种可以预期的结果;而异常则是一种非预期的结果,发生异常可能表示程序中存在BUG或发生了其它不可控的问题。
Go 中主要通过 error 和 panic 分别表示错误和异常[2]
例如,从一个map
查询一个结果时,可以通过额外的布尔值判断是否成功,属于一种预期的结果。
if v, ok := m["key"]; ok {
return v
}
错误
error
Go中的错误类型:error
type error interface {
Error() string
}
内置的 error 接口使得开发人员可以为错误添加任何所需的信息,error 可以是实现 Error() 方法的任何类型,具体例子可参考[2][5]。
Go中errors包提供了几个常用的函数,包括errors.New, errors.Is, errors.As, errors.Unwrap
,以及使用fmt.Errorf
。
erros.Is
判断两个error
是否相等,error.As
判断error
是否为特定类型。
函数通常可在最后一个返回值中返回错误信息,一个简单的应用实例:
package main
import (
"errors"
"fmt"
)
func myF(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("Not legal input ")
}
// 实现
return 0.0, nil
}
func main() {
var m map[string]string
m = make(map[string]string)
m["a"] = "2"
_, ok := m["a"]
_, ok2 := m["b"]
fmt.Println(ok) // true
fmt.Println(ok2) // false
_, e := myF(-1)
_, e2 := myF(2)
fmt.Println(e) // Not legal input
fmt.Println(e2) //
}
异常
defer,panic recover搭配可以处理异常。
defer当程序出现异常,如数组访问越界这类“意料之外”的错误时,它能够导致程序运行崩溃,此时就需要开发人员捕获异常并恢复程序的正常运行流程。捕获异常不是最终的目的。如果异常不可预测,直接输出异常信息是最好的处理方式[1]。
defer
是Go提供的一种延迟执行机制,每次执行 defer,都会将对应的函数压入栈中。在函数返回或者 panic 异常结束时,Go 会依次从栈中取出延迟函数执行。
panic
用于主动抛出程序执行的异常,会终止其后将要执行的代码,并依次逆序执行 panic 所在函数可能存在的 defer 函数列表。
recover
关键字主要用于捕获异常,将程序状态从严重的错误中恢复到正常状态。 必须在 defer 函数中才能生效。
下面是一个defer+panic+recover的代码样例,可以看到,在手动panic后,执行了defer中的输出,并且,a
的值为0,所以如果函数中有panic语句,name函数应该需要返回一个error
。
package main
import "fmt"
func main() {
for i := 0; i < 10; i++ {
a := my(i)
fmt.Println(a)
}
}
func my(i int) int {
defer func() {
if err := recover(); err != nil {
fmt.Println("发生了异常", err)
}
}()
if i != 5 {
return i
} else {
panic("panic")
}
return -1
}
代码输出结果:
0
1
2
发生了异常 panic
0
4
一个处理极端
超级健壮的代码,每个函数开始的地方都添加如下代码:
func myfunc() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
// 函数实现....
}
当然,不要总这么做~~~
如果觉得文章对你有帮助,麻烦 点赞、评论、收藏 你的支持是我最大的动力!!!
最后小编在学习过程中整理了一些学习资料,可以分享给做java的工程师朋友们,相互交流学习,需要的可以加入我的学习交流群 716055499 即可免费获取Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)
作者:dingyu002
来源:dinyu002
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)