18910140161

处理Go语言错误(error)的建议方案

顺晟科技

2021-08-28 09:40:45

333

我认为很多人已经经历过golang语言(Golang)的错误设计。通过返回值强制调用方处理错误。可以忽略或处理(处理也可以继续返回给调用方)。对于Golang的这种设计方式,我们将在代码中写很多if判断。(威廉莎士比亚、Northern Exposure(美国电视剧)、Northern Exposure(美国电视剧))。

1

2

3

4

5

6

7

8

Func main() {

Conent,err 3360=io util . read file(“文件路径”)

If err!=nil{

//错误处理

}else {

Fmt。Println(string(conent))

}

}

这些代码在我们的代码中很重要。大多数情况下,error为nil。这意味着没有任何错误,但如果不是nil,则发生了错误。我们必须处理他(大卫亚设,北方执行)。

错误接口

Error实际上是一个接口,是内置的。让我们来看看它的定义。

1

2

3

4

5

//the error built-in interface type is the conventional interface for

//representing an error condition,with the nil value re presenting no error。

Type error介面{

Error() string

}

Error只有一种方法。实施此方法就是实施Error。约翰肯尼迪,北方执行。现在让我们自己定义错误。

1

2

3

4

5

6

Type fileError struct {

}

Func (Fe * fileerror)错误()字符串{

Return“文件错误”

}

自定义错误

定制文件错误类型以实现错误接口。现在来试试效果。

Func main() {

Conent,err :=openFile()

If err!=nil {

Fmt。Println(err)

} else {

Fmt。Println(string(conent))

}

}

//只模拟一个错误

Func openFile() ([]byte,error) {

Return nil,fileError{}

}

运行模拟代码时,可以查看文件错误的通知。

实际使用过程中可能会发生很多错误。不同的是,错误信息不同。一种方法是定义每个错误的错误类型,如上所示。但是太麻烦了。我们发现Error返回的其实是字符串,我们可以修改以设置这个字符串。

Type fileError struct {

S string

}

Func (Fe * fileerror)错误()字符串{

Return fe.s

}

是的,这样改造后,我们在声明文件管理器时,可以设置错误的文字来提示,以满足我们的其他要求。(大卫亚设,北上广深)。

//只模拟一个错误

Func openFile() ([]byte,error) {

Return nil,fileError{“文件错误,自定义”}

}

是的,是的。已经达到了我们的目的。现在可以更常见,包括修改fileError的名称和创建可以轻松创建其他错误类型的辅助函数。

//blog 3360 www . flysnow . org

//wechat 3360 flysnow _ org

Funcnew(文本字符串)错误{

Return errorstring {文本}

}

Type errorString struct {

S string

}

Func (e * errorstring)错误()字符串{

Return e.s

}

这样,我们就可以通过New函数创建其他错误。这就是我们经常使用的errors。是New函数,是我们逐步解剖进化而来的。现在,我们对Go语言(golang)中内置的错误error有了明确的认识。(威廉莎士比亚,《北方执行报》(Northern Exposure))。

存在的问题

Go语言在错误的设计上很简洁,但对我们开发者来说显然不够。例如,您需要知道错误的详细信息、哪些文件、需要哪些代码行。(大卫亚设,Northern Exposure(美国电视剧),只有这样,我们才能更容易找到问题。

例如,如果想在返回的error中添加更多信息并返回,如上例所示,我们该怎么办?首先,通过Error方法删除原始错误消息,然后直接连接,最后返回errors。可以使用New函数生成新的错误返回。

如果我们以前开发过Java,我们知道Java的例外可能会重叠。也就是说,通过它,我们可以很容易地知道错误的根本原因。因为Java的理想是重叠返回的。不管中间经历了多少包装,我们都可以通过cause找到根本错误的原因。(阿尔伯特爱因斯坦,北方执行)。

解决问题

要解决这些问题,必须先继续扩展errorString,然后添加要保存其他信息的字段。例如,必须记录堆栈信息。

Type stack []uintptr

Type errorString struct {

S string

*stack

}

//www.oicqzone.com

存储堆栈信息的stack字段允许您在生成错误时调用的堆栈信息存储在此字段中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//blog 3360 www . flysnow . org

//wechat 3360 flysnow _ org

Func callers() *stack {

Const depth=32

Var PCs [depth]uintptr

N:=runtime.callers (3,PCs[3360])

Var ST stack=PCs [03360n]

Return ST

}

Funcnew(文本字符串)错误{

Return errorString{

S:文本,

Stack: callers(),

}

}

完美解决,现在再解决,给现有错误附加一些信息的问题呢?(*译者:译者:译者:译者:译者:译者)我相信大家都要有想法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Type withMessage struct {

Cause error

Msg字符串

}

func withmessage(error,消息字符串)error {

If err==nil {

Return nil

}

Return withMessage{

Cause: err,

Msg :消息,

}

}

使用WithMessage函数可以生成原始error软件包下包含包装信息的新错误。

推荐的方案

上面我们在解决问题,是不是采取的方法比较熟悉?特别是从源代码来看,这就是github.com/pkg/errors错误处理库的源代码。

Go语言提供的错误太简单,不能简单地更好地处理问题,甚至不能处理错误,提供更有用的信息,因此,诞生了很多关于错误处理的库。github.com/pkg/errors比较简洁,功能非常强大,受到了很多开发者的欢迎。

它的使用很简单。要生成新错误,可以使用New函数、生成的错误和自己的调用堆栈信息。

1

Funcnew(消息字符串)错误

如果有现成的error,我们需要重新包装他,这时可以选择三个函数。

1

2

3

4

5

6

7

8

//仅添加新信息

Func withmessage (err error、message string) error

//仅添加调用堆栈信息

Func WithStack(err error) error

//同时添加堆栈和信息

Funcwrap (err error、message string) error

事实上,上面的包装与Java的异常包装非常相似,包装的error实际上是Cause。上一章提到错误的根本原因就是这个Cause。因此,该错误处理库为我们提供了Cause函数,使我们能够获得最根本的错误原因。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Funccause(错误)错误{

Type causer界面{

Cause() error

}

For err!=nil {

Cause,ok :=err。(causer)

If!Ok {

布雷克

}

Err=cause。Cause()

}

Return err

}

使用For循环找到最根本的(底部)错误。

上面的错误我们都打包收集了,怎么能打印出存储在他们里面的堆栈、错误的原因等这些信息呢?实际上,此错误处理库的错误类型实现了Formatter接口,并使用fmt .可以通过Printf函数输出相应的错误消息。

%s,%v //功能一样,输出错误消息,不包含堆栈

%q //输出的错误消息用引号括起来,不包含堆栈

% v //输出错误消息和堆栈

如果上面有循环包装错误类型,则递归输出这些错误。

摘要

使用此github.com/pkg/errors错误库,您可以收集更多信息,轻松找到问题。

我们收集的这些信息不仅可以输出到控制台,还可以作为日志使用,还可以输出到相应的日志日志,以便于分析问题。

据说该库将加入Golang标准SDK。加入后,期待补充当前标准仓库中名为errors的package。

相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航