Go语言中的异常处理

Go语言中的异常处理,第1张

在上篇分析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用于主动抛出程序执行的异常,会终止其后将要执行的代码,并依次逆序执行 panic 所在函数可能存在的 defer 函数列表。

recover

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

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/996187.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存