go中的error小结
go中的error
go中的错误处理,是通过返回值的形式来出来,要么你忽略,要么你处理(处理也可以是继续返回给调用者),对于golang这种设计方式,我们会在代码中写大量的if判断,以便做出决定。
func main() {
conent,err:=ioutil.ReadFile("filepath")
if err !=nil{
//错误处理
}else {
fmt.Println(string(conent))
}
}
对于err如果是nil就代表没有错误,如果不是nil就代表程序出问题了,需要对错误进行处理了。
error和panic
error:可预见的错误
panic:不可预见的异常
需要注意的是,你应该尽可能地使用error,而不是使用 panic
和 recover
。只有当程序不能继续运行的时候,才应该使用 panic
和 recover
机制。
panic
有两个合理的用例。
1、发生了一个不能恢复的错误,此时程序不能继续运行。 一个例子就是 web 服务器无法绑定所要求的端口。在这种情况下,就应该使用 panic
,因为如果不能绑定端口,啥也做不了。
2、发生了一个编程上的错误。 假如我们有一个接收指针参数的方法,而其他人使用 nil
作为参数调用了它。在这种情况下,我们可以使用 panic
,因为这是一个编程错误:用 nil
参数调用了一个只能接收合法指针的方法。
在一般情况下,我们不应通过调用panic函数来报告普通的错误,而应该只把它作为报告致命错误的一种方式。当某些不应该发生的场景发生时,我们就应该调用panic。
总结下panic的使用场景
1、空指针引用
2、下标越界
3、除数为0
4、不应该出现的分支,比如default
5、输入不应该引起函数错误
error接口
go中的error是一个接口类型
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
errors.New()
是我们会经常使用的,我们来探究下这个函数
// src/errors/errors.go
func New(text string) error {
return &errorString{text}
}
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
使用 New
函数创建出来的 error
类型实际上是 errors
包里未导出的 errorString
类型,它包含唯一的一个字段 s,并且实现了唯一的方法:Error() string。
举个使用的栗子
func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: square root of negative number")
}
// implementation
}
我们可以使用errors.New
来定制我们需要的错误信息
但是对于上面的报错,我们知道是不知道报错的上下文信息的,我们就知道程序出错了,不利于我们错误的排查。我们可以使用fmt.Errorf
来输出上下文信息。
if f < 0 {
return 0, fmt.Errorf("math: square root of negative number %g", f)
}
通过fmt.Errorf
我们不仅能打印错误,同时还能看到具体什么数数值引起的错误。它会先将字符串格式化,然后再调用errors.New
来创建错误。
当我们想知道错误类型,并且打印错误的时候,直接打印 error
:
fmt.Println(err)
或者:
fmt.Println(err.Error)
fmt
包会自动调用 err.Error()
函数来打印字符串。
注意:对于err我们都是将err放在函数返回值的最后一个,同时对于会出错的函数我们都会返回一个err,当然对于一些函数,我们可能不确定之后是否会有错误的产生,所以一般也是预留一个err的返回。
go中err的困局
在go中,err
的是通过返回值的形式返回。编程人员,要不处理,要不忽略。所以我们的代码就会大量的出现对错误的if
判断。
出于对代码的健壮性考虑,我们对于每一个错误,都是不能忽略的。因为出错的同时,很可能会返回一个 nil 类型的对象。如果不对错误进行判断,那下一行对 nil
对象的操作百分之百会引发一个 panic
。
所以就造成了err
满天飞。
还有比如,我们想对返回的error
附加更多的信息后再返回,比如以上的例子,我们怎么做呢?我们只能先通过Error
方法,取出原来的错误信息,然后自己再拼接,再使用errors.New
函数生成新错误返回。
推荐方法
github.com/pkg/errors
这个包给出了解决的方案。
它的使用非常简单,如果我们要新生成一个错误,可以使用New函数,生成的错误,自带调用堆栈信息。
func New(message string) error
如果有一个现成的error,我们需要对他进行再次包装处理,这时候有三个函数可以选择。
//只附加新的信息
func WithMessage(err error, message string) error
//只附加调用堆栈信息
func WithStack(err error) error
//同时附加堆栈和信息
func Wrap(err error, message string) error
这个错误处理库为我们提供了Cause
函数让我们可以获得最根本的错误原因。
func Cause(err error) error {
type causer interface {
Cause() error
}
for err != nil {
cause, ok := err.(causer)
if !ok {
break
}
err = cause.Cause()
}
return err
}
使用for
循环一直找到最根本(最底层)的那个error
。
以上的错误我们都包装好了,也收集好了,那么怎么把他们里面存储的堆栈、错误原因等这些信息打印出来呢?其实,这个错误处理库的错误类型,都实现了Formatter
接口,我们可以通过fmt.Printf
函数输出对应的错误信息。
%s,%v //功能一样,输出错误信息,不包含堆栈
%q //输出的错误信息带引号,不包含堆栈
%+v //输出错误信息和堆栈
以上如果有循环包装错误类型的话,会递归的把这些错误都会输出。
总结
对于err我们都是将err放在函数返回值的最后一个,同时对于会出错的函数我们都会返回一个err
,当然对于一些函数,我们可能不确定之后是否会有错误的产生,所以一般也是预留一个err
的返回。
Go 中的 error
过于简单,以至于无法记录太多的上下文信息,对于错误包裹也没有比较好的办法。当然,这些可以通过第三方库来解决。
Go 语言使用 error
和 panic
处理错误和异常是一个非常好的做法,比较清晰。至于是使用 error
还是 panic
,看具体的业务场景。
参考
【Go语言(golang)的错误(error)处理的推荐方案】https://www.flysnow.org/2019/01/01/golang-error-handle-suggestion.html
【Golang error 的突围】https://www.cnblogs.com/qcrao-2018/p/11538387.html
【The Go Blog Error handling and Go】https://blog.golang.org/error-handling-and-go
【Go 1.13 errors 基本用法】https://segmentfault.com/a/1190000020398774
【Go与Error的前世今生】https://zhuanlan.zhihu.com/p/55975116
【Go 系列教程 —— 32. panic 和 recover】https://studygolang.com/articles/12785
【Golang错误和异常处理的正确姿势】https://www.jianshu.com/p/f30da01eea97
go中的error小结的更多相关文章
- [转] SpringBoot RESTful 应用中的异常处理小结
[From] https://segmentfault.com/a/1190000006749441 SpringBoot RESTful 应用中的异常处理小结 永顺 2016年08月29日发布 赞 ...
- hiredis中异步的实现小结
hiredis中异步的实现小结 原文: http://blog.csdn.net/l1902090/article/details/3858... 时间: 2014-08-15 前言 一般情况下我们使 ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- 前端开发中的Error以及异常捕获
本文首发于公众号:符合预期的CoyPan 写在前面 在前端项目中,由于JavaScript本身是一个弱类型语言,加上浏览器环境的复杂性,网络问题等等,很容易发生错误.做好网页错误监控,不断优化代码,提 ...
- Linux中syntax error near unexpected token 错误提示解决方法
Linux中syntax error near unexpected token ... 错误提示有一般有两种原因: 1)window和Linux下换行符不一致导致 window下的换行和Linux下 ...
- abaqus2016安装过程中出现error:unable to add abaqus command directory to PATH variable
请问abaqus2016安装过程中出现error:unable to add abaqus command directory to PATH variable是什么原因,怎么解决啊,总是安装失败 这 ...
- MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动
MVC图片上传详解 MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...
- C++中的“error:LNK2005 已经在*.obj中定义”异常问题
C++中的“error:LNK2005 已经在*.obj中定义”异常问题 异常现象如下:
- 180531-Spring中JavaConfig知识小结
原文链接:Spring中JavaConfig知识小结/ Sring中JavaConfig使用姿势 去掉xml的配置方式,改成用Java来配置,最常见的就是将xml中的 bean定义, scanner包 ...
随机推荐
- linux 执行计划任务crontab
crontab 一些常用的命令 service crond start //启动服务 service crond stop //关闭服务 service crond restart //重启服务 se ...
- Flutter配置环境报错“PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”
背景:最近看了很多Flutter漂亮的项目,想要尝试一下.所有环境都搭建好之后,按照文档一步一步配置(抄袭),但始终报如下图错误. PKIX path building failed: sun.sec ...
- Fiddler1 简单使用
1.Fiddler下载地址:https://www.telerik.com/download/fiddler 2.Fiddler设置: Fiddler是强大的抓包工具,它的原理是以web代理服务器的形 ...
- Journal of Proteomics Research | Th-MYCN转基因小鼠的定量蛋白质学分析揭示了Aurora Kinase抑制剂改变代谢途径和增强ACADM以抑制神经母细胞瘤的进展
题目:Quantitative Proteomics of Th-MYCN Transgenic Mice Reveals Aurora Kinase Inhibitor Altered Metabo ...
- 升级Kubernetes 1.18前,你不得不知的9件事
本文来自Rancher Labs 昨天Kubernetes最新版本v1.18已经发布,其包含了38项功能增强,其中15项为稳定版功能.11项beta版功能以及12项alpha版功能.在本文中,我们将探 ...
- 题解 P1457 【城堡 The Castle】
来讨论区大摇大摆地逛了一圈后,我发现竟然大家的代码 都很长 然而代码真的要写那么长吗 首先,来分析问题,1,2,4,8,这些数显然是有特点的,也许你已经想到了没错,它们都是2的次方数. 1是2的0次方 ...
- 动态规划-Minimum Insertion Steps to Make a String Palindrome
2020-01-05 11:52:40 问题描述: 问题求解: 好像多次碰到类似的lcs的变种题了,都是套上了回文的壳.这里再次记录一下. 其实本质就是裸的lcs,就出结果了. public int ...
- shell编程之脚本参数$@,$*,$#,$$,$?的含义
#首先按顺序解释各个参数的含义 1.$0 表示脚本的文件名, 具体的路径信息和执行命令时的相对位置有关,例如 sakura@mi-OptiPlex-7050:~/sh$ sh args.sh arg ...
- [Flink] Flink的waterMark的通俗理解
导读 Flink 为实时计算提供了三种时间,即事件时间(event time).摄入时间(ingestion time)和处理时间(processing time). 遇到的问题: 假设在一个5秒的T ...
- 微信内置浏览器的JsAPI(WeixinJSBridge续)进入全屏
微信内置浏览器的JsAPI(WeixinJSBridge续)进入全屏 之前有写过几篇关于微信内置浏览器(WebView)中特有的Javascript API(Javascript Interface) ...