Golang error使用场景介绍

 更新时间:2023年03月15日 10:57:13   作者:烟草的香味.  
我们在使用Golang时,不可避免会遇到异常情况的处理,与Java、Python等语言不同的是,Go中并没有try...catch...这样的语句块,这个时候我们如何才能更好的处理异常呢?本文来教你正确方法
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

前言

Go的编程中, error的使用场景数不胜数, 主要就是用来处理各种异常情况.

长久以来, 我的使用方式都是这样的:

err := errors.New("fail")
if err != nil{
  //do somethine...
}

简单易懂.

但是, 如果我们的调用链是这样的func1 -> func2 -> func3 -> func4 -> func5, 此时func5发生错误, error逐层向上传递, func1拿到错误后, 因为缺少堆栈信息, 很难根据error还原出错场景.

那么, 根据这个问题, 又该如何处理呢? 很简单, 函数拿到error后, 在其中添加当前上下文信息后再返回不就行了么? 类似于这样:

func func4() error {
	err := func5()
	if err != nil {
		return errors.New(err.Error() + "--func4")
	}
	return nil
}

这当然可以. 但是上层还可能根据不同的error进行不同的异常处理, 这样的话, 使用err == SameErr的判断条件就不好使了.

那么, 如何能够在error中添加信息的同时, 又不丢失原始error的信息呢?

其实, 官方已经做好了类似的支持.

error

Gofmt库中有这样一个error:

type wrapError struct {
	msg string
	err error
}
func (e *wrapError) Error() string {
	return e.msg
}
func (e *wrapError) Unwrap() error {
	return e.err
}

它提供了一个Error方法来实现error接口, 同时还会保存原始的err信息, 可以通过Unwrap获得. 这不就是我们需要得么?

官方对其的使用进行了封装, 包含了:

  • 对异常进行包装
  • 判断指定异常是否存在与包装链中
  • 从包装链中提取指定类型的异常
// 对 err 进行包装.
// 注意, 占位符必须为 %w, 否则返回的就是一个普通 error
err1 := fmt.Errorf("func4: %w", err)
// 判断 err1 中是否包含 SameErr 这个错误
// 相当于对所有 error 依次解包并进行 == 的比较
if errors.Is(err1, SameErr) {
  // 存在 SameErr
}
// 从 err 中获取指定类型的错误
var sameErr *SameErrStruct
if errors.As(err, &sameErr) {
  // 成功从 err 中获取到 SameErr
}
// 对error 进行解包, 若失败返回 nil
retErr := errors.Unwrap(err1)

翻了翻几个方法的源码都比较简单, 在这里就不细述了.

调用栈

但是, 这样一层一层将调用信息返回去, 还是有些麻烦, 有没有什么办法, 能够直接将调用栈放进去呢? 或者说, 在Go中如何获取调用栈呢?

func getStack() {
	// 获取当前调用栈
	pcs := make([]uintptr, 64)
	pcNum := runtime.Callers(2, pcs) // skip 2 是为了跳过 Callers 及其内部函数
	// 调用栈解析
	frames := runtime.CallersFrames(pcs[:pcNum])
	for frame, more := frames.Next(); more; frame, more = frames.Next() {
		fmt.Printf("file: %s, line: %d, func: %s\n", frame.File, frame.Line, frame.Function)
	}
}

OK, 所谓大道至简, error也就这么点东西, 完全能够满足使用了. 再见

到此这篇关于Golang error使用场景介绍的文章就介绍到这了,更多相关Go error内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • Golang通脉之map详情

    Golang通脉之map详情

    这篇文章主要介绍了Golang通脉之map,Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现,map 是一种无序的键值对的集合。map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 map 是一种集合,所以可以像迭代数组和切片那样迭代它
    2021-10-10
  • Golang压缩Jpeg图片和PNG图片的操作

    Golang压缩Jpeg图片和PNG图片的操作

    这篇文章主要介绍了Golang压缩Jpeg图片和PNG图片的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • golang语法使用的注意事项

    golang语法使用的注意事项

    这篇文章主要给大家介绍了关于golang语法使用的一些注意事项,Golang是一种静态类型的编程语言,它支持基本的数据类型,包括整型、浮点型、布尔型、字符串型,需要的朋友可以参考下
    2023-07-07
  • 浅析Golang中Gin框架存在的必要性

    浅析Golang中Gin框架存在的必要性

    在Go语言中,net/http?包提供了一个强大且灵活的标准HTTP库,那为什么还出现了像?Gin?这样的,方便我们构建Web应用程序的第三方库,下面就来和大家简单分析一下
    2023-08-08
  • 浅析golang如何处理json中的null

    浅析golang如何处理json中的null

    json?是一种常用的数据格式,在?go?使用?json?序列化和反序列化时比较方便的,但在使用过程中,会遇到一些问题,比如?null,所以下面我们就来看看golang如何处理json中的null吧
    2023-09-09
  • Golang中interface的基本用法详解

    Golang中interface的基本用法详解

    Go 中接口也是一个使用得非常频繁的特性,好的软件设计往往离不开接口的使用,比如依赖倒置原则(通过抽象出接口,分离了具体实现与实际使用的耦合)。 今天,就让我们来了解一下 Go 中接口的一些基本用法
    2023-01-01
  • 深入理解Go Gin框架中间件的实现原理

    深入理解Go Gin框架中间件的实现原理

    在Go Gin框架中,中间件是一种在请求处理过程中插入的功能模块,它可以用于处理请求的前置和后置逻辑,例如认证、日志记录、错误处理等,本文将给大家介绍一下Go Gin框架中间件的实现原理,需要的朋友可以参考下
    2023-09-09
  • GoLang实现日志收集器流程讲解

    GoLang实现日志收集器流程讲解

    这篇文章主要介绍了GoLang实现日志收集器流程,看日志是开发者平时排查BUG所必须的掌握的技能,但是日志冗杂,所以写个小工具来收集这些日志帮助我们排查BUG,感兴趣想要详细了解可以参考下文
    2023-05-05
  • 深入探讨Go语言中的map是否是并发安全以及解决方法

    深入探讨Go语言中的map是否是并发安全以及解决方法

    这篇文章主要来和大家探讨?Go?语言中的?map?是否是并发安全的,并提供三种方案来解决并发问题,文中的示例代码讲解详细,需要的可以参考一下
    2023-05-05
  • go语言中GOPATH GOROOT的作用和设置方式

    go语言中GOPATH GOROOT的作用和设置方式

    这篇文章主要介绍了go语言中GOPATH GOROOT的作用和设置方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05

最新评论

?


http://www.vxiaotou.com