您好,欢迎访问一九零五行业门户网

关于golang中的错误处理机制的详细介绍

基础
错误处理应该是工程的一部分,golang中的error是一个interface类型,如下:
type error interface { error() string}
凡是实现error()方法的结构,都可以作为错误处理。因此如果函数可能出现错误,那么可以在返回值的最后,返回一个错误,比如:
func foo() error { // ... do something return errors.new("foo error")}
直接返回错误
直接返回错误,类似于直接返回字符串类型的错误,或者错误码之类的。字符串类型的错误,在基础部分提到了。错误码相当于linux、c编程中的错误码,一般我们需要自己定义。举个例子:
package mypkgtype errcode intconst ( err1 = 1 err2 = 2 err3 = 3)func sub(a, b int) (int, errcode) { if b < 0 { return 0, err1 } else if a < b { return 0, err2 } else if a < 0 { return 0, err3 } return a - b}
这种类型的错误,编写简单,但是有两个缺陷:
1、外层如果想要使用错误码,则需要引入这个包,容易出现循环引用的情况。
2、如果包内部修改返回的错误码类型,则外部使用到错误码的地方,都要进行相应的修改,破坏了封闭性。
对于第一个缺陷,可以使用一个第三方的包,专门存放错误码,这个方式值得商榷。永远不要通过判断error()方法返回的字符串的值,来进行对应的错误处理!!!
返回自定义类型的错误
该方式可以返回自定义的类型,并通过断言自定义类型,来进行有关的错误处理;自定义类型可以携带更多的信息,代码实例:
package mainimport ( "errors" "fmt" "runtime/debug")type myerror struct { inner error // 内粗错误 message string // 自定义错误信息 stacktrace string // 堆栈信息 misc map[string]interface{} //其它的一些数据}func (myerror myerror) error() string { return myerror.message}func wraperror(err error, msg string, msgargs ...interface{}) myerror { return myerror{ inner: err, message: fmt.sprintf(msg, msgargs), stacktrace: string(debug.stack()), misc: make(map[string]interface{}), }}func handle(key int) error { if key < 0 { return wraperror(errors.new("key < 0"), "this is an error test") } return nil}func main() { if err := handle(-1); err != nil { if e, ok := err.(myerror); ok { fmt.printf("inner: %v, message: %v, stacktrace: %v\n", e.inner, e.message, e.stacktrace) // 这里输出对应的数据 } }}
这种方式处理问题更加方便,但是仍然可能会有包循环引用的问题。
隐藏内部细节的错误处理
上述两种方式,可以适应一些场景,不过都无法解决可能存在循环依赖的问题。为此,我们使用github.com/pkg/errors的包来解决问题,给出一个代码实例。
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
其实上面的包装,很类似于java的异常包装,被包装的error,其实就是cause,在前面的章节提到错误的根本原因,就是这个cause。所以这个错误处理库为我们提供了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。
相关文章教程推荐:golang教程
以上就是关于golang中的错误处理机制的详细介绍的详细内容。
其它类似信息

推荐信息