自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

新提案:Go panic 能不能加個(gè) PanicError?

開(kāi)發(fā) 前端
在 Go 中對(duì) panic 的優(yōu)化,官方一直都是比較遲緩的。一方面是大佬們比較少寫(xiě)業(yè)務(wù)代碼,另外一方面是類(lèi)似對(duì) panic 加全局?jǐn)r截器避免崩潰等方式,也比較違背開(kāi)創(chuàng)語(yǔ)言時(shí)的哲學(xué)宗旨。

大家好,我是煎魚(yú)。

在我們學(xué)習(xí)和平時(shí)使用 Go 時(shí),一定會(huì)涉及到一個(gè)內(nèi)置函數(shù) panic:

func panic(v any)

調(diào)用該函數(shù)后會(huì)停止代碼的控制流程并開(kāi)始恐慌,達(dá)到扭轉(zhuǎn)當(dāng)前程序控制流的目的。在使用上也常常和 defer 和 recover 關(guān)聯(lián)上。

快速 Demo

以下是一個(gè)簡(jiǎn)單的使用 Demo:

func main() {
 panic("腦子進(jìn)煎魚(yú)了")

 _, err := os.Create("/tmp/file")
 if err != nil {
  log.Fatalln(err)
 }
}

輸出結(jié)果:

$ go run demo.go 
panic: 腦子進(jìn)煎魚(yú)了

goroutine 1 [running]:
main.main()
 /Users/eddycjy/demo.go:10 +0x25
exit status 2

看著都沒(méi)什么問(wèn)題。輸出結(jié)果符合預(yù)期。

一點(diǎn)爭(zhēng)議

由于 Go 起協(xié)程(goroutine)非常簡(jiǎn)單、方便,因此絕大部分開(kāi)發(fā)者在應(yīng)用程序中會(huì)經(jīng)常用 goroutine 去做各種并發(fā)處理的邏輯,一看不小心。就很有可能會(huì)引發(fā)程序中的 panic,導(dǎo)致整個(gè)應(yīng)該程序崩潰,出現(xiàn)事故。(見(jiàn)過(guò)好幾起低級(jí)錯(cuò)誤了,覺(jué)得程序沒(méi)問(wèn)題,所以也沒(méi)有主動(dòng)加防御性代碼)

有一個(gè)比較常見(jiàn)觸發(fā)的場(chǎng)景之一:空指針調(diào)用。時(shí)不時(shí)就能見(jiàn)到幾個(gè)應(yīng)用又誘發(fā)了。

如下代碼:

type T struct {
 Name string
}

func main() {
 var user *T
 go func() {
  // 異步執(zhí)行一些業(yè)務(wù)流程,不小心 panic 了...
  fmt.Println(user.Name)
 }()

 // 做一些事情...
 time.Sleep(time.Second * 1)

 fmt.Println("腦子進(jìn)煎魚(yú)了")
}

輸出結(jié)果:

$ 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

當(dāng)然,這也是有辦法解決的。標(biāo)準(zhǔn)的方式是通過(guò) recover,捕獲 panic。如下代碼:

go func() {
  defer func() {
   if r := recover(); r != nil {
    fmt.Println("Recovered in f", r)
   }
  }()
  // 異步執(zhí)行一些業(yè)務(wù)流程,不小心 panic 了...
  fmt.Println(user.Name)
 }()

輸出結(jié)果:

Recovered in f runtime error: invalid memory address or nil pointer dereference
腦子進(jìn)煎魚(yú)了

又或是基于 goroutine+recvoer 封裝一個(gè)協(xié)程調(diào)用的方法。要求使用這類(lèi)工具庫(kù)來(lái)規(guī)避這個(gè) “坑”。

但不得不說(shuō),很多同學(xué)崩就崩在不覺(jué)得這個(gè)地方會(huì)出問(wèn)題,但就是有問(wèn)題。最后只能一溜煙全都用封裝好的工具庫(kù)來(lái)起 goroutine 了。

新提案:可定義 panic 錯(cuò)誤信息

在前面的案例中,我們可以看到 panic 后現(xiàn)在的輸出信息如下:

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 堆棧跟蹤。

這第一眼看起來(lái)是非常迷惑的,要看錯(cuò)誤信息。如果是程序內(nèi)拋的空指針,還要去翻堆棧信息去猜,再看是哪里的程序。做一輪排查、定位、驗(yàn)證。

因此社區(qū)里 @Mitar 提出了《proposal: runtime: provide a way to format output in unhandled panics[1]》的提案。希望可以針對(duì)意外情況+無(wú)人處理的 panic 錯(cuò)誤進(jìn)行自定義的格式化處理。

提案中希望 panic 新增 PanicError:

type panicError interface {
    error
    PanicError() string
}

如果值實(shí)現(xiàn)了該接口,在 panic 時(shí)則會(huì)優(yōu)先調(diào)用 PanicError 方法,為錯(cuò)誤處理提供一個(gè)可選選項(xiàng),可以為調(diào)試補(bǔ)充額外的有用信息。

這樣就可以進(jìn)一步區(qū)分出 Panic 錯(cuò)誤和普通 Error 錯(cuò)誤的方法,并且針對(duì) Panic 的錯(cuò)誤做各種奇怪的操作和補(bǔ)充。

總結(jié)

今天給大家分享了社區(qū)對(duì)于 panic 優(yōu)化的一個(gè)小點(diǎn)。原提案作者的目的是為了針對(duì) panic 錯(cuò)誤新增 PanicError 方法,若存在則優(yōu)先使用該方法,而非與普通 error 共用 Error 方法,并以此去做好區(qū)分識(shí)別和實(shí)現(xiàn)。

在 Go 中對(duì) panic 的優(yōu)化,官方一直都是比較遲緩的。一方面是大佬們比較少寫(xiě)業(yè)務(wù)代碼,另外一方面是類(lèi)似對(duì) panic 加全局?jǐn)r截器避免崩潰等方式,也比較違背開(kāi)創(chuàng)語(yǔ)言時(shí)的哲學(xué)宗旨。

責(zé)任編輯:武曉燕 來(lái)源: 腦子進(jìn)煎魚(yú)了
相關(guān)推薦

2019-11-21 09:25:23

AI 數(shù)據(jù)人工智能

2022-07-08 08:55:56

Go函數(shù)模型

2013-04-19 10:42:02

打車(chē)軟件大數(shù)據(jù)

2025-04-22 08:00:00

2021-02-25 15:51:41

Go語(yǔ)言模糊測(cè)試功能

2016-05-19 17:10:27

銀行

2022-10-20 08:00:37

機(jī)器人ZadigChatOps

2021-02-26 21:25:08

比特幣投資貨幣

2020-10-16 18:33:18

Rust語(yǔ)言前端開(kāi)發(fā)

2010-04-13 10:02:16

索引

2024-04-26 09:37:43

國(guó)產(chǎn)數(shù)據(jù)庫(kù)開(kāi)發(fā)者

2020-12-21 15:09:23

人工智能安全人臉識(shí)別

2023-04-06 06:55:24

ChatGPTGPT算力

2012-06-13 11:01:59

英特爾

2022-04-24 11:52:04

元宇宙Web3去中心化

2022-12-09 08:22:26

Gradle編譯運(yùn)行

2022-11-07 08:36:11

2021-06-15 11:33:48

監(jiān)控微信聊天前端

2021-12-13 08:52:42

Go 泛型

2024-07-15 11:41:14

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)