golang之errors包
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的新errorWrapf(err error, format string, args ...interface{}) error: 和上面的函数功能是一样的,只不过可以对附加信息进行格式化封装WithMessage(err error, message string) error:该函数基于原始错误err,返回一个附加信息message的新errorWithMessagef(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包的更多相关文章
- Golang学习 - errors 包
------------------------------------------------------------ Go 语言使用 error 类型来返回函数执行过程中遇到的错误,如果返回的 e ...
- 关于golang的time包总结
目录 前言 time包详解 总结 前言 各种编程语言都少不了与时间有关的操作,因为很多判断都是基于时间,因此正确和方便的使用时间库就很重要额. golang提供了import "time&q ...
- Golang爬虫示例包系列教程(一):pedaily.com投资界爬虫
Golang爬虫示例包 文件结构 自己用Golang原生包封装了一个爬虫库,源码见go get -u -v github.com/hunterhug/go_tool/spider ---- data ...
- 一键解决 go get golang.org/x 包失败
问题描述 当我们使用 go get.go install.go mod 等命令时,会自动下载相应的包或依赖包.但由于众所周知的原因,类似于 golang.org/x/... 的包会出现下载失败的情况. ...
- 19-03【golang】strings包
golang的strings包提供了字符串操作的一系列函数.下面做个简单介绍 函数 用法 备注 Compare(a,b sring) 比较两个字符串 Contains(s, substr stri ...
- 关于golang.org/x包问题
关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...
- Golang Gin 项目包依赖管理 godep 使用
Golang Gin 项目包依赖管理 godep 使用 标签(空格分隔): Go 在按照github.com/tools/godep文档go get完包以后,调整项目结构为$GOPATH/src/$P ...
- golang 关于golang.org/x包问题
关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...
- Golang的json包
encoding/json encoding/json是官方提供的标准json, 实现RFC 7159中定义的JSON编码和解码.使用的时候需要预定义struct,原理是通过reflection和in ...
- Golang官方log包详解
Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...
随机推荐
- 一个开源、跨平台的.NET UI框架 - Avalonia UI
前言 今天大姚给大家分享一个开源.免费(MIT License).跨平台的.NET UI框架:Avalonia UI. Avalonia是一个成熟稳定的平台,用于构建桌面.嵌入式.移动的和Web应用程 ...
- pyspark 数据类型及转换
spark 有哪些数据类型 https://spark.apache.org/docs/latest/sql-reference.html Spark 数据类型 Data Types Spark SQ ...
- 一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优.如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误.本次调优的代码是埋点系统中的报表分析功能,小公司,开发结 ...
- Falcon Mamba: 首个高效的无注意力机制 7B 模型
Falcon Mamba 是由阿布扎比的 Technology Innovation Institute (TII) 开发并基于 TII Falcon Mamba 7B License 1.0 的开放 ...
- 深入理解Argo CD工作原理
1. ArgoCD 的架构 ArgoCD 是一个 Kubernetes 原生的持续交付工具,它通过监控 Git 仓库中的应用定义来自动部署应用到 Kubernetes 集群.其核心架构由以下几个关键组 ...
- 扫描全能王启动鸿蒙原生应用开发,系HarmonyOS NEXT智能扫描领域首批
近期,"鸿蒙合作签约暨扫描全能王鸿蒙原生应用开发启动仪式"(简称"签约仪式")正式举行.合合信息与华为达成鸿蒙合作,旗下扫描全能王将基于HarmonyOS NE ...
- 深度学习/NLP中的Attention注意力机制
首先是整体认知,Attention的位置: 传送门1:Attention 机制 传送门2:Attention用于NLP的一些小结 一句话概括:Attention就是从关注全局到关注重点. 借鉴了人类视 ...
- Angular 学习笔记 work with zip (压缩文件格式)
最近在做批量创建. 上回说到了 读写 excel, 那么就可以通过 excel 的资料来创建资料了.但是资料经常会有图片,而 excel 里面放图片有点不太好. 于是就想 upload excel 的 ...
- Identity – Permission Claims & UserClaimsPrincipalFactory
前言 在 Identity – Authorize 有介绍过, Identity 的验证核心是 Claims. 在 Identity – Without Identity Framework 也看到了 ...
- std::stod:“123.456”-> 123.456
std::stod 是 C++ 标准库中一个用于将字符串转换为 double 类型的函数.它属于 <string> 头文件中的函数,通常用于将包含数字的字符串转换为相应的浮点数值. 函数原 ...