Go语言error的设计理念及背景演化详解

 更新时间:2022年12月07日 09:33:35   作者:bluesGavin  
这篇文章主要为大家介绍了Go语言error的设计理念及背景演化详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

背景

作为一门相对新兴的语言,Go 可以说是站在巨人的肩膀上。从 Go 语法上,我们可以看出设计者对其有许多严肃的思考。其中 Error 的处理就是极具标志性的一项。

值得注意的是,Go 中的 Error 一直是一个有争议的内容。很多议案不断的提出又推翻,即便是官方的 error 库也在多个版本中不断迭代。本文内容基于 1.19.3 版本的 Go 编写。

各语言中 Error 的演化

想要了解 Error 在 Go 中占据话题的原因,我们需要先了解 Error 在编程语言中的演化。

C语言

C语言中开发者需要根据函数的返回值作错误判断。每个函数是单返回值,一般通过传递指针作为入参。返回值为 int 类型,表示成功或失败。

显然在这个阶段,语言设计者只单纯地把错误考虑为“异常”情况,由开发者判断函数的执行结果。这种情况下,错误中并没有太多信息。这会加重开发者对错误的处理工作。

C++

进入C++时代以后,语言带来了 exception 。错误会作为一个程序正常执行以外的一个特殊情况被抛出。而开发者可以通过 try....catch.... 对异常作特殊处理。

这种设计模式的影响很广,包括 Javascript 在内很多语言都延续了这种设计。其特点为,开发者可以知道错误在哪里抛出,但不能具体知道调用方会抛出什么异常。

Go 中 Error 的理念

在 Go 的 Error 中,我们可以看到两个 ERROR 的特点。

1. 区分 Error 和 Exception

第一点是,Go 中真正从语言设计上区分开了 Error 和 Exception。Go 的处理异常逻辑不引入 exception ,支持多参数返回,所以开发者可以很容易在函数签名中带上实现了 error interface 的对象,交由调用者处理。

通常如果一个函数返回了 value 和 error , 开发者需要先判定 error,再利用处理 value 处理下一步逻辑。常见代码如下:

value, err := getSomething()
if err != nil{
    // 处理错误
    return
}
// 逻辑处理

另外,Go 中引入了 panic 机制,它与其他语言的 exception 不完全一样。在其他语言中,当程序抛出异常时,相当于把 exception 抛给开发者处理。而 Go 中的 panic 是专门,针对真正意外,不可恢复的情况,如索引越界、不可恢复的环境问题、栈溢出。

同时,GO 也提供了从 panic 中恢复的接口—— recover 。但这不意味着开发者应该把其当作 try... catch... 使用。而是应该当作是程序崩溃后的特殊处理的最后机会。在 Go 的设计中,panic 一旦触发,说明程序应该要退出了。但在某些业务场景下,我们可能还会有日志上报,日志打印,信息通知等操作。此时,就应该考虑使用 recover。

2.Error是一个接口

第二点是,Error 在 Go 中其实是一个普通的接口。它不仅保存着错误的信息,还提供了一系列的方式供开发者使用。因此开发者可以自行拓展,嵌套,封装新的 error ,为项目提供自定义错误模块。

由此看来,Error 在 Go 中并不像其他语言一样,是一个特殊的类型。它只是一个普通的值,开发者完全可以自己实现一套新的 Error 接口。但更多时候,官方的 errors 库已经可以覆盖绝大多数场景了。

因此, Go 的设计并不是在定义一套新的 Error 机制。而是在制定一套 Error 在代码逻辑中处理的规范。你不必完全遵守这套规范,但在各种实际开发经验总结来看,Go 的这种设计模式确实赢得了很多开发者的青睐。

示例代码:

// 创建一个error
newErr := errors.New("一个错误")
// 判断error类型
if errors.Is(newErr, fs.ErrNotExist) {
	fmt.Println("file does not exist")
} else {
	fmt.Println(err)
}

总结

Go 之所以从诞生至今,吸引了这么多的粉丝。处理语言的机制以外,更多的就是它的设计理念。而本文讲述的 error 就是其中一部分。我们在使用 Go 开发时,除了按照它推荐的规范编码至于,还应该关心、理解它的设计。只有这样,才能写出更优秀的作品。

进一步阅读 官方 errors 库文档地址:pkg.go.dev/errors

以上就是Go语言error的设计理念及背景演化详解的详细内容,更多关于Go error设计理念的资料请关注脚本之家其它相关文章!

相关文章

  • 关于Go语言中特有的设计模式与实现方式讲解

    关于Go语言中特有的设计模式与实现方式讲解

    虽然Go语言没有像其他语言那样明确的设计模式,但在实践中,开发者们仍然发现了一些在Go语言中特别适用的设计模式和实现方式,本文就来和大家一一进行讲解
    2023-05-05
  • 详解Go sync 同步原语

    详解Go sync 同步原语

    Go 中不仅有 channel 这种 CSP 同步机制,还有 sync.Mutex、sync.WaitGroup 等比较原始的同步原语,使用它们,可以更灵活的控制数据同步和多协程并发,这篇文章主要介绍了Go sync 同步原语,需要的朋友可以参考下
    2023-12-12
  • 详解Go中的高效切片拼接和Go1.22提供的新方法

    详解Go中的高效切片拼接和Go1.22提供的新方法

    在 Go 语言中,切片拼接是一项常见的操作,但如果处理不当,可能会导致性能问题或意外的副作用,本文将详细介绍几种高效的切片拼接方法,希望对大家有所帮助
    2024-01-01
  • Go 字符串格式化的实例代码详解

    Go 字符串格式化的实例代码详解

    这篇文章主要介绍了Go 字符串格式化的实例代码详解,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • Golang pprof性能测试与分析讲解

    Golang pprof性能测试与分析讲解

    刚开始接触go就遇到了一个内存问题,在进行内存分析的时候发现了一下比较好的工具,在此留下记录,下面这篇文章主要给大家介绍了关于go性能分析工具pprof的性能测试,需要的朋友可以参考下
    2023-04-04
  • 一文详解Golang中的切片数据类型

    一文详解Golang中的切片数据类型

    这篇文章主要介绍了一文详解Golang中的切片数据类型,切片是一个种特殊的数组。是对数组的一个连续片段的引用,所以切片是一个引用类型
    2022-09-09
  • Go语言轻量级线程Goroutine用法实例

    Go语言轻量级线程Goroutine用法实例

    这篇文章主要介绍了Go语言轻量级线程Goroutine用法,实例分析了goroutine使用技巧,需要的朋友可以参考下
    2015-02-02
  • Go实现MD5加密的三种方法小结

    Go实现MD5加密的三种方法小结

    本文主要介绍了Go实现MD5加密的三种方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Golang 类型转换的实现(断言、强制、显式类型)

    Golang 类型转换的实现(断言、强制、显式类型)

    将一个值从一种类型转换到另一种类型,便发生了类型转换,在go可以分为断言、强制、显式类型转换,本文就详细的介绍一下这就几种转换方式,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 重学Go语言之如何使用Redis

    重学Go语言之如何使用Redis

    Redis是我们开发应用程序中很常用的NoSQL数据库,那么在Go语言中要如何连接和操作Redis呢,在这篇文章中,我们就来一起来探究一下吧
    2023-08-08

最新评论