欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang中Error的設(shè)計與實踐詳解

 更新時間:2023年08月17日 11:31:24   作者:用戶4129026645654  
這篇文章主要為大家詳細介紹了Golang中Error的設(shè)計以及是具體如何處理錯誤的相關(guān)知識,文中的示例代碼簡潔易懂,需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下

如果你對于 Go 的 Error 設(shè)計不太熟悉也不習(xí)慣,為什么許多接口都需要返回 error 接口類型的值呢?什么時候該處理 error,什么時候該拋出 error,什么時候又該忽略 error ?Go 設(shè)計者又為什么要這樣設(shè)計 error 呢?想必剛接觸 Golang 的同學(xué)也會和我一樣有類似的疑惑,在讀了 TGPL 以及 Go Blog 相關(guān)的章節(jié)/內(nèi)容后,我嘗試回答一下這些問題。

在第 1 、2小節(jié)我將嘗試回答 error 是什么,它是如何設(shè)計的,以及為什么這樣設(shè)計。

在第 3 小節(jié)我將回答在 Coding 時,如何處理錯誤。

Error 是什么

在 Go built-in 包中,Error 被設(shè)計為一個接口。

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
   Error() string
}

Go 的設(shè)計理念是:失敗(failure)只是一種常見的行為。

因此對于那些失敗被視作理所當(dāng)然的函數(shù)可以返回一個額外的結(jié)果——error,通常是最后一個返回值。而如果失敗只有一種可能的原因,那么只需要返回一個 bool 值即可。

上述做法在 Go 的源碼或接口設(shè)計中很常見。舉兩個例子:

以常見的 Reader 接口為例, Read 方法讀取至多 len(p) 個字節(jié)到 p 中,返回讀取的字節(jié)數(shù) n 和讀取過程中可能發(fā)生的錯誤 err。

type Reader interface {
   Read(p []byte) (n int, err error)
}

當(dāng)我們使用 map 時經(jīng)常遇到的一種情況是:確定某個鍵是否在 map 中。但是 map 在該鍵不存在時也會返回默認值,此時可以使用帶 bool 返回值的形式:

if val, ok := m["key"]; ok {
    // do something
} else {
    // do other things
}

Error 的設(shè)計

Go 的錯誤處理設(shè)計與其他語言的異常不同。Go 中的 error 就是一個普通的值對象,而其他語言如 Java 中的 Exception 將會造成程序控制流的終止和其他行為,Exception 與普通的值不同。雖然 Go 也有類似的異常機制 —— panic,但它僅用于報告完全無法預(yù)料的錯誤(可能有 Bug),而不應(yīng)該是一個健壯程序應(yīng)該返回的程序錯誤(這一點與 Java 等語言不同)。

關(guān)于 Go 為什么這樣設(shè)計的原因,Kernighan 在 《The Go Programming Language》中給出解釋:"The reason for this design is that exceptions tend to entangle the description of an error with the control flow required to handle it, often leading to an undesirable outcome: routine errors are reported to the end user in the form of an incomprehensible stack trace, full of information about the structure of the program but lacking intelligible context about what went wrong"。

即:因為異常會將錯誤的描述和處理錯誤的控制流糾纏在一起,通常會導(dǎo)致程序錯誤以一種難以理解的棧追蹤的方式被報告給終端用戶,這種方式充滿了程序結(jié)構(gòu)的信息,但是缺少關(guān)于哪里出錯的易于理解的上下文信息。

相反,Go 程序使用普通的程序控制流機制如 if 以及 return 來對 error 作出響應(yīng),這種設(shè)計雖然要求 Gophers 更加關(guān)注錯誤處理邏輯,但這正是它想做到的點。即“好的程序應(yīng)該考慮到所有可能的錯誤,并且對其進行處理”。

Go 將 error 設(shè)計為一個接口,只需要實現(xiàn) Error() string 方法,返回有意義、簡練的錯誤描述信息即可。這也使得我們可以以任何的方式來自定義錯誤。

Tips: 建議在底層只需要返回清晰地錯誤信息,每一層包裹一些重要并且簡潔的上下文信息,并且最終在程序的頂層或者某一個不得不處理的層級處理該錯誤。

正是這種方式,在 Go 中也將這種層層包裹的錯誤稱之為錯誤鏈。由此,在 Go 1.13 之后出現(xiàn)了一些新的設(shè)計以支持這種錯誤鏈的處理方式。其中最簡單的錯誤鏈就是如下所述的層層包裹的文本信息(或者程序調(diào)用棧信息)

genesis: crashed: no parachute: G-switch failed: bad relay orientation

Error 處理策略

最常見的做法是傳遞錯誤。即將被調(diào)用程序產(chǎn)生的錯誤傳遞給調(diào)用方,由上層決定如何處理,并且如果需要的話可以附加一些本程序所知的上下文信息。

obj, err := doSomething()
if err != nil {
    return err
}
// do otherthings

第二種,對于那些表示短暫的、難以預(yù)測的錯誤,可以去重試該操作,當(dāng)然要施加一定的重試次數(shù)限制

for i := 0; i < times; i++ {
    res, err := run()
    if err == nil {
        return res
    }
    // do something like log or metrics
}

第三種,如果無法繼續(xù)往下執(zhí)行,調(diào)用方打印錯誤信息并且優(yōu)雅地結(jié)束程序

if err := initT(); err != nil {
    panic("something wrong") // though this way is not elegant
}

第四種,在某些情況錯誤并不致命,也可以只是記錄下錯誤并且繼續(xù)往下執(zhí)行。這種情況,最多導(dǎo)致程序缺少部分功能,但總比什么都不做要好。

obj, err := doSomething()
if err != nil {
    logs.CtxInfo(ctx, "something wrong but it doesnot cause serious consequences")
}
// and continue to do something

最后一種,調(diào)用方確信不可能發(fā)生的錯誤或者即使發(fā)生了也不會有任何問題,可以忽略它。

// could not encode failed
bytes, _ := json.Marshal(obj)

最后,Go 的錯誤處理比較特別,一般在檢查錯誤之后,先處理失敗情況然后再處理成功情形——"Happy Path"??梢员WC所有錯誤均被處理之后再開心的處理正常情形(提醒 Programmer 不要忘記處理異常情況),并且可以減少縮進層級(在其他語言也被稱為 "Guard"模式)。

obj, err := getObj()
if err != nil {
    // do some err handling policy
    return fmt.Errorf("could not get obj, err = %v", err)
}
// happy path

到此這篇關(guān)于Golang中Error的設(shè)計與實踐詳解的文章就介紹到這了,更多相關(guān)golang error內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang環(huán)境搭建及打包和工具鏈詳解

    Golang環(huán)境搭建及打包和工具鏈詳解

    這篇文章主要介紹了Golang環(huán)境搭建及打包和工具鏈,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 詳解Go語言中單鏈表的使用

    詳解Go語言中單鏈表的使用

    鏈表由一系列結(jié)點(鏈表中每一個元素稱為結(jié)點)組成,結(jié)點可以在運行時動態(tài)生成。本文將通過實例為大家詳解Go語言中單鏈表的常見用法,感興趣的可以了解一下
    2022-08-08
  • Windows10系統(tǒng)下安裝Go環(huán)境詳細步驟

    Windows10系統(tǒng)下安裝Go環(huán)境詳細步驟

    Go語言是谷歌推出的一款全新的編程語言,可以在不損失應(yīng)用程序性能的情況下極大的降低代碼的復(fù)雜性,這篇文章主要給大家介紹了關(guān)于Windows10系統(tǒng)下安裝Go環(huán)境的詳細步驟,需要的朋友可以參考下
    2023-11-11
  • Go?for-range?的?value值地址每次都一樣的原因解析

    Go?for-range?的?value值地址每次都一樣的原因解析

    循環(huán)語句是一種常用的控制結(jié)構(gòu),在?Go?語言中,除了?for?關(guān)鍵字以外,還有一個?range?關(guān)鍵字,可以使用?for-range?循環(huán)迭代數(shù)組、切片、字符串、map?和?channel?這些數(shù)據(jù)類型,這篇文章主要介紹了Go?for-range?的?value值地址每次都一樣的原因解析,需要的朋友可以參考下
    2023-05-05
  • Go語言跨平臺時字符串中的換行符如何統(tǒng)一?

    Go語言跨平臺時字符串中的換行符如何統(tǒng)一?

    本文介紹了Go語言中統(tǒng)一換行符的方法,包括使用`strings.ReplaceAll`函數(shù)將Windows風(fēng)格的換行符`\r\n`替換為Unix風(fēng)格的換行符`\n`,或?qū)\n`替換為`\r\n`,統(tǒng)一換行符可以避免不同平臺間顯示不一致、傳輸時出現(xiàn)多余的換行符或丟失換行符,以及解析錯誤等問題
    2024-11-11
  • 利用Go語言快速實現(xiàn)一個極簡任務(wù)調(diào)度系統(tǒng)

    利用Go語言快速實現(xiàn)一個極簡任務(wù)調(diào)度系統(tǒng)

    任務(wù)調(diào)度(Task Scheduling)是很多軟件系統(tǒng)中的重要組成部分,字面上的意思是按照一定要求分配運行一些通常時間較長的腳本或程序。本文將利用Go語言快速實現(xiàn)一個極簡任務(wù)調(diào)度系統(tǒng),感興趣的可以了解一下
    2022-10-10
  • 一篇文章帶你搞懂Go語言標準庫Time

    一篇文章帶你搞懂Go語言標準庫Time

    在我們開發(fā)的過程中,每個項目都需要時間這一類的函數(shù),此時對time這個包的研究深度就顯得尤為重要,這篇文章主要給大家介紹了關(guān)于如何通過一篇文章帶你搞懂Go語言標準庫Time的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • golang的空標識符理解

    golang的空標識符理解

    今天小編就為大家分享一篇關(guān)于golang的空標識符理解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Go基礎(chǔ)系列:Go切片(分片)slice詳解

    Go基礎(chǔ)系列:Go切片(分片)slice詳解

    這篇文章主要介紹了Go語言中的切片(分片)slice詳細說明?,需要的朋友可以參考下
    2022-04-04
  • Golang?Gin?中間件?Next()方法示例詳解

    Golang?Gin?中間件?Next()方法示例詳解

    這篇文章主要介紹了Golang?Gin?中間件?Next()方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04

最新評論