Golang error使用场景介绍

 更新时间:2023年03月15日 10:57:13   作者:烟草的香味.  
我们在使用Golang时,不可避免会遇到异常情况的处理,与Java、Python等语言不同的是,Go中并没有try...catch...这样的语句块,这个时候我们如何才能更好的处理异常呢?本文来教你正确方法

前言

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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 安装Sublime Text支持Go插件的方法步骤

    安装Sublime Text支持Go插件的方法步骤

    本文主要介绍了安装Sublime Text支持Go插件的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • GORM不定参数的用法最佳实践

    GORM不定参数的用法最佳实践

    这篇文章主要为大家介绍了GORM不定参数的用法最佳实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Go语言实现websocket推送程序

    Go语言实现websocket推送程序

    这篇文章主要介绍了Go语言实现websocket推送程序,WebSocket是基于TCP的一个双向传输数据的协议,和HTTP协议一样,是在应用层的,他的出现,是为了解决网页进行持久双向传输数据的问题
    2023-01-01
  • 利用GO语言实现多人聊天室实例教程

    利用GO语言实现多人聊天室实例教程

    聊天室的实现大家应该都遇到过,这篇文章主要给大家介绍了关于利用GO语言实现多人聊天室的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2018-03-03
  • 分析Go错误处理优化go recover机制缺陷

    分析Go错误处理优化go recover机制缺陷

    这篇文章主要为大家介绍了分析Go错误处理优化go recover机制缺陷示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Go 使用Unmarshal将json赋给struct出错的原因及解决

    Go 使用Unmarshal将json赋给struct出错的原因及解决

    这篇文章主要介绍了Go 使用Unmarshal将json赋给struct出错的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Go语言实现JSON解析的神器详解

    Go语言实现JSON解析的神器详解

    php转go是大趋势,越来越多公司的php服务都在用go进行重构,重构过程中,会发现php的json解析操作是真的香。本文和大家分享了一个Go语言实现JSON解析的神器,希望对大家有所帮助
    2023-01-01
  • 关于golang中平行赋值浅析

    关于golang中平行赋值浅析

    这篇文章主要给大家介绍了关于golang中平行赋值的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • 一文带你吃透Golang中net/http标准库服务端

    一文带你吃透Golang中net/http标准库服务端

    这篇文章将从服务端(Server)作为切入点和大家分享一下Go语言net/http标准库的实现逻辑,进而一步步分析http标准库内部是如何运作的,感兴趣的可以了解下
    2024-03-03
  • 详解golang开发中http请求redirect的问题

    详解golang开发中http请求redirect的问题

    这篇文章主要介绍了详解golang开发中http请求redirect的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论