Golang新提案:panic 能不能加个 PanicError?

 更新时间:2023年12月26日 11:27:12   作者:煎鱼  
这篇文章主要为大家介绍了Golang的新提案关于panic能不能加个PanicError的问题分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

在我们学习和平时使用 Go 时,一定会涉及到一个内置函数 panic:

func panic(v any)

调用该函数后会停止代码的控制流程并开始恐慌,达到扭转当前程序控制流的目的。在使用上也常常和 defer 和 recover 关联上。

快速 Demo

以下是一个简单的使用 Demo:

func main() {
 panic("脑子进煎鱼了")
 _, err := os.Create("/tmp/file")
 if err != nil {
  log.Fatalln(err)
 }
}

输出结果:

$ go run demo.go 
panic: 脑子进煎鱼了
goroutine 1 [running]:
main.main()
 /Users/eddycjy/demo.go:10 +0x25
exit status 2

看着都没什么问题。输出结果符合预期。

一点争议

由于 Go 起协程(goroutine)非常简单、方便,因此绝大部分开发者在应用程序中会经常用 goroutine 去做各种并发处理的逻辑,一看不小心。就很有可能会引发程序中的 panic,导致整个应该程序崩溃,出现事故。(见过好几起低级错误了,觉得程序没问题,所以也没有主动加防御性代码)

有一个比较常见触发的场景之一:空指针调用。时不时就能见到几个应用又诱发了。

如下代码:

type T struct {
 Name string
}
func main() {
 var user *T
 go func() {
  // 异步执行一些业务流程,不小心 panic 了...
  fmt.Println(user.Name)
 }()
 // 做一些事情...
 time.Sleep(time.Second * 1)
 fmt.Println("脑子进煎鱼了")
}

输出结果:

$ go run demo.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x1087178]

goroutine 6 [running]:
main.main.func1()
 /Users/eddycjy/demo.go:16 +0x18
created by main.main in goroutine 1
 /Users/eddycjy/demo.go:14 +0x31
exit status 2

当然,这也是有办法解决的。标准的方式是通过 recover,捕获 panic。如下代码:

go func() {
  defer func() {
   if r := recover(); r != nil {
    fmt.Println("Recovered in f", r)
   }
  }()
  // 异步执行一些业务流程,不小心 panic 了...
  fmt.Println(user.Name)
 }()

输出结果:

Recovered in f runtime error: invalid memory address or nil pointer dereference
脑子进煎鱼了

又或是基于 goroutine+recvoer 封装一个协程调用的方法。要求使用这类工具库来规避这个 “坑”。

但不得不说,很多同学崩就崩在不觉得这个地方会出问题,但就是有问题。最后只能一溜烟全都用封装好的工具库来起 goroutine 了。

新提案:可定义 panic 错误信息

在前面的案例中,我们可以看到 panic 后现在的输出信息如下:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x1087178]

goroutine 6 [running]:
main.main.func1()
 /Users/eddycjy/demo.go:16 +0x18
created by main.main in goroutine 1
 /Users/eddycjy/demo.go:14 +0x31
exit status 2

程序输出了恐慌值和 goroutine 堆栈跟踪。

这第一眼看起来是非常迷惑的,要看错误信息。如果是程序内抛的空指针,还要去翻堆栈信息去猜,再看是哪里的程序。做一轮排查、定位、验证。

因此社区里 @Mitar 提出了《proposal: runtime: provide a way to format output in unhandled panics[1]》的提案。希望可以针对意外情况+无人处理的 panic 错误进行自定义的格式化处理。

提案中希望 panic 新增 PanicError:

type panicError interface {
    error
    PanicError() string
}

如果值实现了该接口,在 panic 时则会优先调用 PanicError 方法,为错误处理提供一个可选选项,可以为调试补充额外的有用信息。

这样就可以进一步区分出 Panic 错误和普通 Error 错误的方法,并且针对 Panic 的错误做各种奇怪的操作和补充。

总结

今天给大家分享了社区对于 panic 优化的一个小点。原提案作者的目的是为了针对 panic 错误新增 PanicError 方法,若存在则优先使用该方法,而非与普通 error 共用 Error 方法,并以此去做好区分识别和实现。

在 Go 中对 panic 的优化,官方一直都是比较迟缓的。一方面是大佬们比较少写业务代码,另外一方面是类似对 panic 加全局拦截器避免崩溃等方式,也比较违背开创语言时的哲学宗旨。

参考资料

proposal: runtime: provide a way to format output in unhandled panics: https://github.com/golang/go/issues/63455 

以上就是Golang新提案panic 能不能加个 PanicError的问题分析内容,更多关于Go panic PanicError的资料请关注脚本之家其它相关文章!

相关文章

  • Goland调节字体大小的设置(编辑区,terminal区,页面字体)

    Goland调节字体大小的设置(编辑区,terminal区,页面字体)

    这篇文章主要介绍了Goland调节字体大小的设置(编辑区,terminal区,页面字体),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go使用Viper管理配置文件的方法步骤

    go使用Viper管理配置文件的方法步骤

    在项目开发中,需要把一些配置配置提取出来,方便配置和管理,可以使用Viper工具,Viper 是 Go 应用程序的完整配置解决方案,也支持从环境变量中读取,本文给大家介绍了go使用Viper管理配置文件的方法步骤,需要的朋友可以参考下
    2024-07-07
  • go goroutine 怎样进行错误处理

    go goroutine 怎样进行错误处理

    在 Go 语言程序开发中,goroutine 的使用是比较频繁的,因此在日常编码的时候 goroutine 里的错误处理,怎么做会比较好呢,本文就来详细介绍一下
    2021-07-07
  • Golang使用minio替代文件系统的实战教程

    Golang使用minio替代文件系统的实战教程

    本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对象以及设置过期策略等,需要的朋友可以参考下
    2025-01-01
  • Go语言中 Channel 详解

    Go语言中 Channel 详解

    Go 语言中的 channel 是实现 goroutine 间无锁通信的关键机制,他使得写多线程并发程序变得简单、灵活、触手可得。下面就个人理解对 channel 使用过程中应该注意的地方进行一个简要的总结。
    2018-10-10
  • 超全讲解Golang中defer关键字的用法

    超全讲解Golang中defer关键字的用法

    本文将从一个资源回收问题引入,引出defer关键字,并对其进行基本介绍,从而让大家对Go语言中的defer有更深入的了解,需要的小伙伴可以学习一下
    2023-05-05
  • go语言在请求http时加入自定义http header的方法

    go语言在请求http时加入自定义http header的方法

    这篇文章主要介绍了go语言在请求http时加入自定义http header的方法,实例分析了Go语言http请求的原理与操作技巧,需要的朋友可以参考下
    2015-03-03
  • go程序执行交叉编译的流程步骤

    go程序执行交叉编译的流程步骤

    go程序可用通过交叉编译的方式在一个平台输出多个平台可运行的二进制包,本文给大家详细介绍了go程序执行交叉编译的流程步骤,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2024-07-07
  • 详解Go语言实现线性查找算法和二分查找算法

    详解Go语言实现线性查找算法和二分查找算法

    线性查找又称顺序查找,它是查找算法中最简单的一种。二分查找,也称折半查找,相比于线性查找,它是一种效率较高的算法。本文将用Go语言实现这两个查找算法,需要的可以了解一下
    2022-12-12
  • 对Go语言中的context包源码分析

    对Go语言中的context包源码分析

    这篇文章主要对Go语言中的context包源码进行分析,context包析是1.15,context包定义了一个Context类型过这个Context接口类型, 就可以跨api边界/跨进程传递一些值,下面我们就来对context包源码进行分析,需要的小伙伴可以参考一下
    2022-02-02

最新评论