本文摘自php中文网,作者V,侵删。

基础
错误处理应该是工程的一部分,Golang中的error是一个interface
类型,如下:
1 2 3 | type error interface {
Error() string
}
|
凡是实现Error()
方法的结构,都可以作为错误处理。因此如果函数可能出现错误,那么可以在返回值的最后,返回一个错误,比如:
1 2 3 4 | func foo() error {
return errors.New( "foo error" )
}
|
直接返回错误
直接返回错误,类似于直接返回字符串类型的错误,或者错误码之类的。字符串类型的错误,在基础部分提到了。错误码相当于Linux、C编程中的错误码,一般我们需要自己定义。举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package mypkg
type ErrCode int
const (
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()方法返回的字符串的值,来进行对应的错误处理!!!
返回自定义类型的错误
该方式可以返回自定义的类型,并通过断言自定义类型,来进行有关的错误处理;自定义类型可以携带更多的信息,代码实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package main
import (
"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
的包来解决问题,给出一个代码实例。
1 | func New(message string) error
|
如果有一个现成的error,我们需要对他进行再次包装处理,这时候有三个函数可以选择。
1 2 3 4 5 6 | func WithMessage(err error, message string) error
func WithStack(err error) error
func Wrap(err error, message string) error
|
其实上面的包装,很类似于Java的异常包装,被包装的error,其实就是Cause,在前面的章节提到错误的根本原因,就是这个Cause。所以这个错误处理库为我们提供了Cause函数让我们可以获得最根本的错误原因。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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中的错误处理机制的详细介绍的详细内容,更多文章请关注木庄网络博客!!
相关阅读 >>
手把手教你实现golang跨平台编译
聊聊gost的gosafely
go使用iris问题之数字变科学计数法
golang的压测工具 hey
go 语言学习之初步认识
golang一行代码把array/slice转成逗号分隔的字符串
golang看什么书
手撸golang go与微服务 saga模式之1
golang sleep为什么没有返回值
聊聊dubbo-go-proxy的jtypes
更多相关阅读请进入《golang》频道 >>
老貘
一个与时俱进的Go编程知识库。
转载请注明出处:木庄网络博客 » 关于golang中的错误处理机制的详细介绍