最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

Error 是什么

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

// 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è)計(jì)理念是:失敗(failure)只是一種常見(jiàn)的行為。

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

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

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

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

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

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

Error 的設(shè)計(jì)

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

關(guān)于 Go 為什么這樣設(shè)計(jì)的原因,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"。

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

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

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

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

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

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

Error 處理策略

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

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

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

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

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

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

第四種,在某些情況錯(cuò)誤并不致命,也可以只是記錄下錯(cuò)誤并且繼續(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ā)生的錯(cuò)誤或者即使發(fā)生了也不會(huì)有任何問(wèn)題,可以忽略它。

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

最后,Go 的錯(cuò)誤處理比較特別,一般在檢查錯(cuò)誤之后,先處理失敗情況然后再處理成功情形——"Happy Path"??梢员WC所有錯(cuò)誤均被處理之后再開心的處理正常情形(提醒 Programmer 不要忘記處理異常情況),并且可以減少縮進(jìn)層級(jí)(在其他語(yǔ)言也被稱為 "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è)計(jì)與實(shí)踐詳解的文章就介紹到這了,更多相關(guān)golang error內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你入門Go語(yǔ)言中定時(shí)任務(wù)庫(kù)Cron的使用

    一文帶你入門Go語(yǔ)言中定時(shí)任務(wù)庫(kù)Cron的使用

    在平時(shí)的開發(fā)需求中,我們經(jīng)常會(huì)有一些重復(fù)執(zhí)行的操作需要觸發(fā)執(zhí)行,說(shuō)白了就是定時(shí)任務(wù)。這篇文章主要給大家介紹一下如何在go項(xiàng)目中實(shí)現(xiàn)一個(gè)crontab功能,感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助
    2022-08-08
  • Go語(yǔ)言的WebAssembly實(shí)戰(zhàn)開發(fā)

    Go語(yǔ)言的WebAssembly實(shí)戰(zhàn)開發(fā)

    Go語(yǔ)言的WebAssembly支持為Web開發(fā)帶來(lái)了新的可能性,本文主要介紹了Go語(yǔ)言與WebAssembly的結(jié)合,內(nèi)容包括編譯方法、JavaScript交互、性能優(yōu)化技巧和實(shí)戰(zhàn)案例,感興趣的可以了解一下
    2026-05-05
  • go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    這篇文章主要介紹了go-zero 如何應(yīng)對(duì)海量定時(shí)/延遲任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Go語(yǔ)言實(shí)現(xiàn)單端口轉(zhuǎn)發(fā)到多個(gè)端口

    Go語(yǔ)言實(shí)現(xiàn)單端口轉(zhuǎn)發(fā)到多個(gè)端口

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言實(shí)現(xiàn)單端口轉(zhuǎn)發(fā)到多個(gè)端口,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的小伙伴可以了解下
    2024-02-02
  • 淺析Golang中調(diào)度器的關(guān)鍵機(jī)制與性能

    淺析Golang中調(diào)度器的關(guān)鍵機(jī)制與性能

    Golang的調(diào)度器是其并發(fā)模型的核心組件,負(fù)責(zé)管理Goroutine的調(diào)度和執(zhí)行,本文將從理論和代碼層面分析Golang調(diào)度器的關(guān)鍵機(jī)制,感興趣的可以了解下
    2025-03-03
  • Golang?strings包常用字符串操作函數(shù)

    Golang?strings包常用字符串操作函數(shù)

    Golang?中的字符串統(tǒng)一使用?UTF-8?(屬于Unicode編碼的一種實(shí)現(xiàn)方式)進(jìn)行編碼,本篇文章將結(jié)合具體實(shí)例對(duì)常用的字符串操作函數(shù)進(jìn)行介紹,感興趣的可以了解一下
    2021-12-12
  • Go語(yǔ)言使用SQLite實(shí)現(xiàn)本地存儲(chǔ)的示例詳解

    Go語(yǔ)言使用SQLite實(shí)現(xiàn)本地存儲(chǔ)的示例詳解

    在開發(fā)工具類軟件、桌面應(yīng)用或者移動(dòng)端時(shí),我們經(jīng)常需要一個(gè)輕量級(jí)數(shù)據(jù)庫(kù)來(lái)做本地存儲(chǔ),本文將帶你一步步用 Go 搭建一個(gè) SQLite 本地存儲(chǔ)的示例,希望對(duì)大家有所幫助
    2025-08-08
  • go常用指令之go?mod詳解

    go常用指令之go?mod詳解

    當(dāng)go命令運(yùn)行時(shí),它查找當(dāng)前目錄然后查找相繼的父目錄來(lái)找出 go.mod,下面這篇文章主要給大家介紹了關(guān)于go常用指令之go?mod的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • 使用Go?http重試請(qǐng)求的示例

    使用Go?http重試請(qǐng)求的示例

    開發(fā)中對(duì)于http請(qǐng)求是經(jīng)常遇到,一般可能網(wǎng)絡(luò)延遲或接口返回超時(shí),這篇文章主要介紹了使用Go?http重試請(qǐng)求的示例,需要的朋友可以參考下
    2022-08-08
  • Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié)

    Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié)

    在日常的一些開發(fā)場(chǎng)景中,我們需要去和遠(yuǎn)程服務(wù)器進(jìn)行一些通信,本文主要介紹了Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04

最新評(píng)論

奉贤区| 溧阳市| 盐津县| 邛崃市| 宽甸| 湾仔区| 吴桥县| 石嘴山市| 肇庆市| 河西区| 万载县| 容城县| 江门市| 正宁县| 始兴县| 昭觉县| 通化市| 怀仁县| 莱西市| 达拉特旗| 上林县| 曲水县| 崇文区| 黄骅市| 宕昌县| 玉溪市| 视频| 伊宁市| 顺平县| 奎屯市| 巴中市| 孝昌县| 霞浦县| 沁水县| 永顺县| 徐州市| 玉门市| 定安县| 瓦房店市| 安多县| 沈阳市|