日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
你對Go錯(cuò)誤處理的4個(gè)誤解!

大家好,我是煎魚。

為涼山州等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及涼山州網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、涼山州網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

Go 語言中錯(cuò)誤處理的機(jī)制一直是各大 Gopher 熱議的問題。甚至一直有人寄望 Go 支持 throw 和 catch 關(guān)鍵字,實(shí)現(xiàn)與其他語言類似的特性。社區(qū)里的討論也從未停過。

今天煎魚帶大家了解幾個(gè) Go 語言的錯(cuò)誤處理中,大家最關(guān)心,也是最容易被誤解、被嫌棄的問題:

  • 為什么不支持 try-catch?
  • 為什么不支持全局捕獲的機(jī)制?
  • 為什么要這么設(shè)計(jì)錯(cuò)誤處理?
  • 未來的錯(cuò)誤處理機(jī)制會怎么樣?

落寞的 try-catch

在 Go1 時(shí),大家知道基本不可能支持。于是打起了 Go2 的主意。為什么 Go 就不能支持 try-catch 組合拳?

上一年宣發(fā)了 Go2 的構(gòu)想,所以在 2020 年就有小伙伴乘機(jī)提出過類似 《proposal: Go 2: use keywords throw, catch, and guard to handle errors[1]》的提案,這可是其他語言都支持的,Go 語言怎么了?

下面來自該提案的演示,Go1 的錯(cuò)誤處理:

 
 
 
 
  1. type data struct {}
  2. func (d data) bar() (string, error) {
  3.     return "", errors.New("err")
  4. }
  5. func foo() (data, error) {
  6.     return data{}, errors.New("err")
  7. }
  8. func do () (string, error) {
  9.     d, err := foo()
  10.     if err != nil {
  11.         return "", err
  12.     }
  13.     s, err := d.bar()
  14.     if err != nil {
  15.         return "", err
  16.     }
  17.     return s, nil
  18. }

新提案所改造的方式:

 
 
 
 
  1. type data struct {}
  2. func (d data) bar() string {
  3.     throw "", errors.New("err")
  4. }
  5. func foo() (d data) {
  6.     throw errors.New("err")
  7.     return
  8. }
  9. func do () (string, error) {
  10.     catch err {
  11.         return "", err 
  12.     }
  13.     s := foo().bar()
  14.     return s, nil
  15. }

不過答復(fù)非常明確,@davecheney 在底下回復(fù)“以最強(qiáng)烈的措辭,不(In the strongest possible terms, no)”。這可讓人懵了圈,為什么這么硬呢?

其實(shí) Go 官方早在《Error Handling — Problem Overview[2]》提案早已明確提過,Go 官方在設(shè)計(jì)上會有意識地選擇使用顯式錯(cuò)誤結(jié)果和顯式錯(cuò)誤檢查。

結(jié)合《language: Go 2: error handling meta issue[3]》可得知,要拒絕 try-catch 關(guān)鍵字的主要原因是:

  • 會涉及到額外的流程控制,因?yàn)槭褂?try 的復(fù)雜表達(dá)式,會導(dǎo)致函數(shù)意外返回。
  • 在表達(dá)式層面上沒有流程控制結(jié)構(gòu),只有 panic 關(guān)鍵字,它不只是從一個(gè)函數(shù)返回。

說白了,就是設(shè)計(jì)理念不合,加之實(shí)現(xiàn)上也不大合理。在以往的多輪討論中早已被 Go 團(tuán)隊(duì)拒絕了。

反之 Go 團(tuán)隊(duì)倒是一遍遍在回答這個(gè)問題,已經(jīng)不大耐煩了,直接都整理了 issues 版的 FAQ 了。

想捕獲所有 panic

在 Go 語言中,有一個(gè)點(diǎn),很多新同學(xué)會不一樣碰到的。那就是在 goroutine 中如果 panic 了,沒有加 recover 關(guān)鍵字(有時(shí)候也會忘記),就會導(dǎo)致程序崩潰。

又或是以為加了 recover 就能保障一個(gè) goroutine 下所派生出來的 goroutine 所產(chǎn)生的 panic,一勞永逸。

但現(xiàn)實(shí)總是會讓人迷惑,我經(jīng)常會看到有同學(xué)提出類似的疑惑:

來自 Go 讀者交流群

這時(shí)候,有其他語言經(jīng)驗(yàn)的同學(xué)中,又有想到了一個(gè)利器。能不能設(shè)置一個(gè)全局的錯(cuò)誤處理 handler。

像是 PHP 語言也可以有類似的方法:

 
 
 
 
  1. set_error_handler();
  2. set_exception_handler();
  3. register_shutdown_function();

顯然,Go 語言中并沒有類似的東西。歸類一下,我們聚焦以下兩個(gè)問題:

  • 為什么 recover 不能捕獲更上層的 panic?
  • 為什么 Go 沒有全局的錯(cuò)誤處理方法?

源碼層面

如果是講設(shè)計(jì)的話,其實(shí)只是通過 Go 的 GMP 模型和 defer+panic+recver 的源碼剖析就能知道了。

本質(zhì)上 defer+panic 都是掛載在 G 上的,可查看我以前寫的《深入理解 Go panic and recover[4]》,你會有更多深入的理解。

設(shè)計(jì)思想

在本文中我們不能僅限于源碼,需要更深挖,Go 設(shè)計(jì)者他的思想是什么,為什么就是不支持?

在 Go issues 中《proposal: spec: allow fatal panic handler[5]》、《No way to catch errors from goroutines automatically[6] 》分別的針對性探討過上述問題。

Go 團(tuán)隊(duì)的大當(dāng)家 @Russ Cox 給出了明確的答復(fù):Go 語言的設(shè)計(jì)立場是錯(cuò)誤恢復(fù)應(yīng)該在本地完成,或者完全在一個(gè)單獨(dú)的進(jìn)程中完成。

這就是為什么 Go 語言不能跨 goroutines 從 panic 中恢復(fù),也不能從 throw 中恢復(fù)的根本原因,是語言設(shè)計(jì)層面的思想所決定。

在源碼剖析時(shí),你所看到的整套 GMP+defer+panic+recover 的機(jī)制機(jī)制,就是跟隨著這個(gè)設(shè)計(jì)思想去編寫和發(fā)展的。

設(shè)計(jì)思想決定源碼實(shí)現(xiàn)。

建議方式

從 Go 語言層面去動搖這個(gè)設(shè)計(jì)思想,目前來看可能性很低。至少 2021 年的現(xiàn)在沒有看到改觀。

整體上會建議提供公共的 Go 方法去規(guī)避這種情況。參考 issues 所提供的范例如下:

 
 
 
 
  1. recovery.SafeGo(logger, func() {
  2.     method(all parameters)
  3. })
  4. func SafeGo(logger logging.ILogger, f func()) {
  5.  go func() {
  6.   defer func() {
  7.    if panicMessage := recover(); panicMessage != nil {
  8.     ...
  9.    }
  10.   }()
  11.   f()
  12.  }()
  13. }

是不是感覺似曾相識?

每家公司的內(nèi)部庫都應(yīng)該有這么一個(gè)工具方法,規(guī)避偶爾忘記的 goroutine recover 所引發(fā)的奇奇怪怪問題。

也可以參照建議,利用一個(gè)單獨(dú)的進(jìn)程(Go 語言中是 goroutine)去統(tǒng)一處理這些 panic,不過這比較麻煩,較少見。

未來會如何

Go 社區(qū)對 Go 語言未來的錯(cuò)誤處理機(jī)制非常關(guān)心,因?yàn)?Go1 已經(jīng)米已成炊,希望在 Go2 上解決錯(cuò)誤處理機(jī)制的問題。

期望 Go2 核心要處理的包含如下幾點(diǎn)(#40432):

對于 Go2,我們希望使錯(cuò)誤檢查更加輕便,減少專門用于錯(cuò)誤檢查的 Go 程序代碼的數(shù)量。我們還想讓寫錯(cuò)誤處理更方便,減少程序員花時(shí)間寫錯(cuò)誤處理的可能性。

錯(cuò)誤檢查和錯(cuò)誤處理都必須保持明確,即在程序文本中可見。我們不希望重復(fù)異常處理的陷阱。

現(xiàn)有的代碼必須繼續(xù)工作,并保持與現(xiàn)在一樣的有效性。任何改變都必須與現(xiàn)有的代碼相互配合。

為此,許多人提過不少新的提案...很可惜,截止 2021.08 月底為止,有許多人試圖改變語言層面以達(dá)到這些目標(biāo),但沒有一個(gè)新的提案被接受。

現(xiàn)在也有許多變更并入 Go2 提案,主要是 error-handling 方面的優(yōu)化。

大家有興趣可以看看我之前寫的:《先睹為快,Go2 Error 的掙扎之路》,相信能給你帶來不少新知識。

總結(jié)

看到這里,我們不由得想到。為什么,為什么在 21 世紀(jì)前者已經(jīng)有了這么多優(yōu)秀的語言,Go 語言的錯(cuò)誤處理機(jī)制依然這么的難抉擇?

顯然 Go 語言的開發(fā)團(tuán)隊(duì)是有自己的設(shè)計(jì)哲學(xué)和思想的,否則 “l(fā)ess is more” 也不會如此廣泛流傳。設(shè)身處地的理解 Go 官方的想法,而不是一味地單向理解,會對我們未來的編程之路更好。

當(dāng)然,這存在著一系列既要也要的問題,不好處理。歡迎大家關(guān)注煎魚,后續(xù)我們也可以面向 Go 后續(xù)的錯(cuò)誤處理持續(xù)的關(guān)注和討論!

參考資料

[1]proposal: Go 2: use keywords throw, catch, and guard to handle errors: https://github.com/golang/go/issues/40583

[2]Error Handling — Problem Overview: https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md

[3]language: Go 2: error handling meta issue: https://github.com/golang/go/issues/40432

[4]深入理解 Go panic and recover: https://eddycjy.com/posts/go/panic/2019-05-21-panic-and-recover/

[5]proposal: spec: allow fatal panic handler: https://github.com/golang/go/issues/32333

[6]No way to catch errors from goroutines automatically: https://github.com/golang/go/issues/20161


分享標(biāo)題:你對Go錯(cuò)誤處理的4個(gè)誤解!
路徑分享:http://www.5511xx.com/article/dhpsese.html