基础

错误处理应该时工程的一部分,Golang中的error是一个interface类型,如下:

type error interface {Error() string
}

凡是实现Error()方法的结构,都可以作为错误处理。因此如果函数可能出现错误,那么可以在返回值的最后,返回一个错误,比如:

func foo() error {// ... do somethingreturn errors.New("foo error")
}

直接返回错误

直接返回错误,类似于直接返回字符串类型的错误,或者错误码之类的。字符串类型的错误,在基础部分提到了。错误码相当于Linux C编程中的错误码,一般我们需要自己定义。举个例子:

package mypkgtype ErrCode intconst (ERR1 = 1ERR2 = 2ERR3 = 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的包来解决问题,给出一个代码实例,以下内容来自这篇博客

它的使用非常简单,如果我们要新生成一个错误,可以使用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

其实上面的包装,很类似于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

参考资料

  • https://ethancai.github.io/2017/12/29/Error-Handling-in-Go/
  • https://www.flysnow.org/2019/01/01/golang-error-handle-suggestion.html
  • https://dave.cheney.net/paste/gocon-spring-2016.pdf

Golang错误处理机制相关推荐

  1. Golang 错误处理机制详解

    本文介绍Golang错误处理机制,包括不同类型错误处理.定义运行时错误等内容. golang错误处理机制 Go错误处理类似C语言,没有提供任何异常,以及类java语言使用的try/catch异常处理机 ...

  2. golang错误处理机制(异常处理)

    看一段代码,引入错误处理 对上面代码的总结: 在默认情况下,当发生错误后(panic) ,程序就会退出(崩溃.) 如果我们希望:当发生错误后,可以捕获到错误,并进行处理,保证程序可以继续执行.还可 以 ...

  3. Go语言的错误异常处理机制及其应用

    一.背景 在日常编写golang程序或阅读别人的golang代码时,我们总会看到如下的一堆代码块: xx, err = func(xx) if err != nil {//do sth. to tac ...

  4. 标准错误处理机制——error

    在 Golang 中,错误处理机制一般是函数返回时使用的,是对外的接口,而异常处理机制 panic-recover 一般用在函数内部. error 类型介绍 error 类型实际上是抽象了 Error ...

  5. Golang错误和异常处理的正确姿势

    Golang错误和异常处理的正确姿势 错误和异常是两个不同的概念,非常容易混淆.很多程序员习惯将一切非正常情况都看做错误,而不区分错误和异常,即使程序中可能有异常抛出,也将异常及时捕获并转换成错误.从 ...

  6. SpringBoot之错误处理机制

    文章目录 1.SpringBoot默认的错误处理机制 2.错误处理原理 (1)DefaultErrorAttributes (2)BasicErrorController:处理默认的/error请求 ...

  7. Vue.js@2.6.10更新内置错误处机制,Fundebug同步支持相应错误监控

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: Fundebug 的 JavaScript 错误监控插件同步支持 Vue.js 异步错误监控. Vue.js 从诞生至 ...

  8. Laravel 5.5 的错误异常处理机制以及应用实例

    一.前言 我们在开发项目中,难免会因为逻辑上的失误而报错,这些报错的展现形式也就是框架封装好的异常处理机制.在项目上线之前,我们还可以根据框架提供的报错信息来锁定错误代码的位置.但是项目上线之后我们是 ...

  9. .net错误处理机制

    .net错误处理机制 让我们想想,ASP.NET为我们提供了几种错误处理机制?如果同时使用他们是不是有一定的优先级?.NET提供了四种错误处理机制,它们有一定的优先级顺序:Page_Error事件&g ...

最新文章

  1. 机器人是如何规划路径的?动画演示一下吧
  2. Node.js process 模块常用属性和方法
  3. FD.io/VPP — 常用指令集合
  4. 虚拟化:IT技术的第三次革命
  5. Python爬虫实战(4):抓取淘宝MM照片
  6. Vue+Openlayer使用Draw实现交互式绘制多边形并获取面积
  7. maven整合@data注解_springboot整合spring Cache(redis)
  8. mysql 乐观锁_使用Mysql乐观锁解决并发问题
  9. Apache Cassandra 在 Facebook 的应用
  10. 9.获取当前时区时间和utc时间的工具方法
  11. 关闭和启动Oracle的几种方法总结
  12. Oracle宣布在云上正式上线 自治事务处理数据库
  13. 第 8 章 MybatisPlus 扩展
  14. 切图时图片的选择:JPG、PNG、GIF的区别
  15. MySQL_Ubuntu安装
  16. 全能地图工具共享及操作规范
  17. 80端口为什么要备案_成都为什么要登记icp备案需要多久
  18. Maven3.8.5安装与配置
  19. Proxmox VE 配置桌面虚拟化
  20. 哥尼斯堡的“七桥问题” (25 分)

热门文章

  1. weex默认的flex布局_CSS flex布局入门
  2. 升级 卸载 ubuntu的kernel版本
  3. stm32F103驱动ADS1115程序-4通道可用-ALERT中断可用-ADC芯片,应该是最全了
  4. 移植ubuntu14.04根文件系统至beaglebone开发板探索
  5. 完整的Flex多文件上传实例
  6. 算法不会,尚能饭否之排序——折半插入排序(Binary Insert Sort)
  7. Linux命令行设置环境变量
  8. Codeforces205E Little Elephant and Furik and RubikLittle Elephant and Furik and Rubik
  9. 【codevs1519】 过路费
  10. 【转】去除inline-block元素的间隙