内容简介:对于一开始写 go 代码的开发者来说,可能最受不了的一件事情就是对在 go 中,这样想要自定义一个
对于一开始写 go 代码的开发者来说,可能最受不了的一件事情就是对 error
的处理,之前听一个同事说他写到至今 go 代码,其中有将近 40% 的代码都是 if err != nil {...}
,确实让人有点崩溃。写 go 写了一段时间之后觉得也没什么,起码觉得这样看起来也挺清晰的。
在 go 中, error
是一个 interface{}
类型,它只包含一个 Error()
方法,类型声明如下:
type error interface { Error() string }
这样想要自定义一个 error
就很简单,比如 net package
中定义 DNSError
就是按照如下方法定义的:
type DNSError struct { Err string // description of the error Name string // name looked for Server string // server used IsTimeout bool // if true, timed out; not all timeouts set this IsTemporary bool // if true, error is temporary; not all errors set this } func (e *DNSError) Error() string { if e == nil { return " <nil> " } s := "lookup " + e.Name if e.Server != "" { s += " on " + e.Server } s += ": " + e.Err return s } </nil>
而在编写 go 代码时,最普遍使用的 error
实现是 errors package
中的,其中的代码也非常简单,只有几行:
package errors func New(text string) error { return &errorString{text} } type errorString struct { s string } func (e *errorString) Error() string { return e.s }
在实际开发过程中,我们处理错误的时候如果仅仅是将报错展示出去那就很简单,只需要通过调用 Error()
方法就可以拿到报错的描述,但是大部分情况下,我们往往需要知道这是属于哪种类型的报错,以便做不同的处理,这时候便有好几种解决方案。
直接进行匹配
预先使用 errors package
的 New(text string)
方法定义好 error
,然后将获取到的 error 同已经定义好的 error 做比较,因为最终获取到的 error
和已经定义好的 error
其实都是遵循 error interface
的 struct
类型,而 golang 中的 struct
是可以进行比较的。比如在 gorm
这个数据库 ORM
的 package
中,就使用了 errors package
来定义了 ErrRecordNotFound
。
// ErrRecordNotFound returns a "record not found error". Occurs only when attempting to query the database with a struct; querying with a slice won't return this error var ErrRecordNotFound = errors.New("record not found")
说到这里,gorm 中有一个我觉得很有意思的一个设计,因为在数据库执行过程中会执行多条语句,此时可能会有多条 error
信息,gorm 的处理是定义了 type Errors []error
这样一个类型,然后让它遵循 error interface
,通过这样达到一个一条 error
包含多条 error
的目的。
通过 interface 的类型转换
有时候我们需要自己定义 error
类型以满足开发需求,比如除了仅仅知道报错信息之外,我们还需要针对报错增加错误码,因为 error
是一个 interface
,所以实现起来很简单。在具体开发过程中,拿到一条 error
对它进行类型转换,转换成自定义的 error
就可以做我们想做的操作了。
我们还是用 gorm 来举例,上面我们说 gorm 中定义了一个 Errors
类型,它遵循了 error interface
,并实际上是一个 []error
类型,所以我们拿到一条 error 可以对它做类型转换,比如下面这个方法:
// IsRecordNotFoundError returns true if error contains a RecordNotFound error func IsRecordNotFoundError(err error) bool { if errs, ok := err.(Errors); ok { for _, err := range errs { if err == ErrRecordNotFound { return true } } } return err == ErrRecordNotFound }
Go 2.0 Draft
虽说 go 目前的 error
处理写起来简单粗暴,看代码看起来也挺简单,但是毕竟这也都是 9102 年了,这种对错误的处理总觉得很落后,好在 Google 在 go 2 草案中开始对此进行了改进,增加了 check
和 handle
两个关键字来对 error 进行处理,在这里简单介绍一下。
比如说我们需要实现一个 copyFile
的操作,根据 go 2 的草案,增加 check
和 handle
之后,就很简单了:
func CopyFile(src, dst string) error { handle err { return err } r := check os.Open(src) defer r.Close() w := check os.Create(dst) handle err { w.Close() os.Remove(dst) } check io.Copy(w, r) check w.Close() return nil }
其中,在需要检查 error 的操作中增加 check
,然后配合 handle
代码块来进行对 error 的处理, handle
代码块可以有多个,会按照从下往上的顺序以此执行,这看上去感觉有点像 try-catch
的处理,比现在的错误处理写起来要爽很多。
以上所述就是小编给大家介绍的《golang error 设计》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 架构设计(7)——如何设计一个架构
- 架构设计(8)—高可用架构设计
- 如何设计实时数据平台(设计篇)
- Token经济设计专家叶开:Token设计画布与10大设计模式
- 数据可视化设计(1)情感化设计指导可视化设计理念
- 架构设计笔记(八):详细方案设计
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机网络(第4版)
[美] James F. Kurose、[美] Keith W. Ross / 陈鸣 / 机械工业出版社 / 2009-11 / 66.00元
本书采用了独创的自顶向下方法,即从应用层开始沿协议栈向下讲解计算机网络的基本原理,强调应用层范例和应用编程接口,内容深入浅出,注重教学方法,理论与实践相结合。第3版的内容相应更新并反映了网络领域的最新进展,如增加了无线和移动网络一章,扩充了对等网络、BGP、MPLS、网络安全、广播选路和因特网编址及转发方面的材料;还增加了一套实用的实验,并修订了习题。本书适合作为计算机、电子、通信工程相关专业的本......一起来看看 《计算机网络(第4版)》 这本书的介绍吧!