errors包常用方法

func Unwrap(err error) error                 // 获得err包含下一层错误
func Is(err, target error) bool // 判断err是否包含target
func As(err error, target interface{}) bool // 判断err是否为target类型

自定义错误信息

errors.New("这是自定义错误")

# 使用fmt进行错误包装
fmt.Errorf("error: %w", err)

errors.Is()

作用:判断被包装过的error是否包含指定错误

var BaseErr = errors.New("base error")

func main() {
err1 := fmt.Errorf("wrap base: %w", BaseErr)
err2 := fmt.Errorf("wrap err1: %w", err1)
println(err2 == BaseErr) if !errors.Is(err2, BaseErr) { // err2错误 是否在BaseErr错误树中
panic("err2 is not BaseErr")
}
println("err2 is BaseErr")
} //输出:
//false
//err2 is BaseErr

errors.As()

作用:判断被包装过的error是否为指定类型

具体说明:提取指定类型的错误,判断包装的 error 链中,某一个 error 的类型是否与 target 相同,并提取第一个符合目标类型的错误的值,将其赋值给 target

type TypicalErr struct {
e string
} func (t TypicalErr) Error() string {
return t.e
} func main() {
err := TypicalErr{"typical error"}
err1 := fmt.Errorf("wrap err: %w", err)
err2 := fmt.Errorf("wrap err1: %w", err1)
var e TypicalErr
if !errors.As(err2, &e) {
panic("TypicalErr is not on the chain of err2")
}
println("TypicalErr is on the chain of err2")
println(err == e)
}
//输出:
//TypicalErr is on the chain of err2
//true

errors的最佳实践:

遵循以下建议,我们可以更好地处理 error :

  • 1、一个 error,应该只被处理一次
  • 2、让 error 包含更多的信息
  • 3、原始 error,应保证完整性,不被破坏
  • 4、error 需要被日志记录

为了确保 error 处理的有效性,对于某一层来说,应该保证每个错误只被处理一次,要么打印 error 信息,要么将其传递给上一层,而不是每一层都独立打印 error 信息。

同时,在传递错误给上一层时,应该附带有用的额外信息,并确保不破坏原始错误的完整性,以保证错误的可追溯性。最后,通过记录错误日志可以帮助我们进行问题排查。

我们可以借助第三方库 github.com/pkg/errors 来完成我们的需求。

github.com/pkg/errors 提供了很多实用的函数,例如:

  • Wrap(err error, message string) error:该函数基于原始错误 err,返回一个带有堆栈跟踪信息和附加信息 message 的新 error
  • Wrapf(err error, format string, args ...interface{}) error: 和上面的函数功能是一样的,只不过可以对附加信息进行格式化封装
  • WithMessage(err error, message string) error:该函数基于原始错误 err,返回一个附加信息 message 的新 error
  • WithMessagef(err error, format string, args ...interface{}) error: 和上面的函数功能是一样的,只不过可以对附加信息进行格式化封装
  • Cause(err error) error:该函数用于提取 err 中的原始 error,它会递归地检查 error,直到找到最底层的原始 error,如果存在的话
// controller / middleware
res, err := service.GetById(ctx, id)
if err != nil {
log.Errorf(ctx, "service.GetById failed, original error: %T %v", errors.Cause(err), errors.Cause(err))
log.Errorf(ctx, "stack trace: \n%+v\n", err)
······
}
······ // service
article, err := dao.GetById(ctx, id)
if err != nil {
return errors.WithMessage(err, "dao.GetById failed")
}
······ // dao
······
if err != nil {
return errors.Wrapf(err, "GetById failed, id=%s, error=%v", id, err)
}
······

当在 Dao 层遇到原始错误 Original Error 后,使用 errors.Wrap() 对错误进行封装。这个封装操作可以在保留根因(Origin error)的同时,提供堆栈信息,并添加额外的上下文信息,然后将封装后的错误传递给上一层处理。

service 层接收到 error 之后,使用 errors.WithMessage() 函数,将额外的信息附加到错误上,并继续将错误向上层传递,直至到达 controller 层。在 controller 层,我们可以打印出根因的类型、信息以及堆栈信息,以便更好地进行问题排查。

 
 

golang之errors包的更多相关文章

  1. Golang学习 - errors 包

    ------------------------------------------------------------ Go 语言使用 error 类型来返回函数执行过程中遇到的错误,如果返回的 e ...

  2. 关于golang的time包总结

    目录 前言 time包详解 总结 前言 各种编程语言都少不了与时间有关的操作,因为很多判断都是基于时间,因此正确和方便的使用时间库就很重要额. golang提供了import "time&q ...

  3. Golang爬虫示例包系列教程(一):pedaily.com投资界爬虫

    Golang爬虫示例包 文件结构 自己用Golang原生包封装了一个爬虫库,源码见go get -u -v github.com/hunterhug/go_tool/spider ---- data ...

  4. 一键解决 go get golang.org/x 包失败

    问题描述 当我们使用 go get.go install.go mod 等命令时,会自动下载相应的包或依赖包.但由于众所周知的原因,类似于 golang.org/x/... 的包会出现下载失败的情况. ...

  5. 19-03【golang】strings包

    golang的strings包提供了字符串操作的一系列函数.下面做个简单介绍 函数 用法 备注 Compare(a,b sring) 比较两个字符串   Contains(s, substr stri ...

  6. 关于golang.org/x包问题

    关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...

  7. Golang Gin 项目包依赖管理 godep 使用

    Golang Gin 项目包依赖管理 godep 使用 标签(空格分隔): Go 在按照github.com/tools/godep文档go get完包以后,调整项目结构为$GOPATH/src/$P ...

  8. golang 关于golang.org/x包问题

    关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...

  9. Golang的json包

    encoding/json encoding/json是官方提供的标准json, 实现RFC 7159中定义的JSON编码和解码.使用的时候需要预定义struct,原理是通过reflection和in ...

  10. Golang官方log包详解

    Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...

随机推荐

  1. 一个开源、跨平台的.NET UI框架 - Avalonia UI

    前言 今天大姚给大家分享一个开源.免费(MIT License).跨平台的.NET UI框架:Avalonia UI. Avalonia是一个成熟稳定的平台,用于构建桌面.嵌入式.移动的和Web应用程 ...

  2. pyspark 数据类型及转换

    spark 有哪些数据类型 https://spark.apache.org/docs/latest/sql-reference.html Spark 数据类型 Data Types Spark SQ ...

  3. 一次Java性能调优实践【代码+JVM 性能提升70%】

    这是我第一次对系统进行调优,涉及代码和JVM层面的调优.如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误.本次调优的代码是埋点系统中的报表分析功能,小公司,开发结 ...

  4. Falcon Mamba: 首个高效的无注意力机制 7B 模型

    Falcon Mamba 是由阿布扎比的 Technology Innovation Institute (TII) 开发并基于 TII Falcon Mamba 7B License 1.0 的开放 ...

  5. 深入理解Argo CD工作原理

    1. ArgoCD 的架构 ArgoCD 是一个 Kubernetes 原生的持续交付工具,它通过监控 Git 仓库中的应用定义来自动部署应用到 Kubernetes 集群.其核心架构由以下几个关键组 ...

  6. 扫描全能王启动鸿蒙原生应用开发,系HarmonyOS NEXT智能扫描领域首批

    近期,"鸿蒙合作签约暨扫描全能王鸿蒙原生应用开发启动仪式"(简称"签约仪式")正式举行.合合信息与华为达成鸿蒙合作,旗下扫描全能王将基于HarmonyOS NE ...

  7. 深度学习/NLP中的Attention注意力机制

    首先是整体认知,Attention的位置: 传送门1:Attention 机制 传送门2:Attention用于NLP的一些小结 一句话概括:Attention就是从关注全局到关注重点. 借鉴了人类视 ...

  8. Angular 学习笔记 work with zip (压缩文件格式)

    最近在做批量创建. 上回说到了 读写 excel, 那么就可以通过 excel 的资料来创建资料了.但是资料经常会有图片,而 excel 里面放图片有点不太好. 于是就想 upload excel 的 ...

  9. Identity – Permission Claims & UserClaimsPrincipalFactory

    前言 在 Identity – Authorize 有介绍过, Identity 的验证核心是 Claims. 在 Identity – Without Identity Framework 也看到了 ...

  10. std::stod:“123.456”-> 123.456

    std::stod 是 C++ 标准库中一个用于将字符串转换为 double 类型的函数.它属于 <string> 头文件中的函数,通常用于将包含数字的字符串转换为相应的浮点数值. 函数原 ...