日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

由于Golang的語言設(shè)計(jì)的原因,不管是不是愿意,每個(gè)golang開發(fā)者的幾乎每一段代碼都需要與error做纏斗。下面我就簡單分析一下golang中的error相關(guān)。

轉(zhuǎn)自:https://www.jianshu.com/p/606d0e60c58d

參考:Go語言中文文檔:www.topgoer.com

error是什么?

首先需要明確的一點(diǎn)是,golang中對于error類型的定義是什么?不同于很多語言的exception機(jī)制,golang在語言層面經(jīng)常需要顯示的做錯(cuò)誤處理。其實(shí)從本質(zhì)上來講,golang中的error就是一個(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
}

和所有接口含義一樣,nil表示零值。

before Go1.13

在golang的1.13版本之前,官方給到的錯(cuò)誤處理方法寥寥無幾,只有用來構(gòu)造無額外參數(shù)的錯(cuò)誤的errors.New和構(gòu)造帶額外參數(shù)的錯(cuò)誤的fmt.Errorf。當(dāng)時(shí),經(jīng)常需要使用標(biāo)準(zhǔn)庫之外的擴(kuò)展庫來支持更豐富發(fā)錯(cuò)誤構(gòu)造和處理,比如由Dave Cheney主導(dǎo)的github.com/pkg/errors。
這些額外的error庫主要的關(guān)注點(diǎn)在于提供方法用于描述錯(cuò)誤的層級。回到上面的錯(cuò)誤本身的定義,只是一個(gè)包含Error方法的接口,本身缺乏對于類似其他語言中類似traceback的描述能力,無法追蹤錯(cuò)誤的詳細(xì)棧信息。
而以github.com/pkg/errors為代表的庫,通過實(shí)現(xiàn)Wrap和Cause方法對來提供了包裝/拆包錯(cuò)誤的能力,提供了類似traceback(但需要開發(fā)者自己定義額外信息)和逐層解析并比較錯(cuò)誤的能力。通過這個(gè)方法對,我們可以實(shí)現(xiàn)下面的用例:

// 為錯(cuò)誤提供更豐富的上下文信息,方便定位錯(cuò)誤
if _, err := ioutil.ReadAll(r);err != nil {
        return errors.Wrap(err, "read file failed")
}

// 判斷錯(cuò)誤的根錯(cuò)誤是什么,根據(jù)最初的錯(cuò)誤類型判斷需要走什么錯(cuò)誤處理邏輯
switch err := errors.Cause(err).(type) {
case *io.EOF:
        // handle specifically
default:
        // unknown error
}

After Go1.13

對于上面描述的錯(cuò)誤處理,相比于較為成熟的exception處理模式,天生缺乏錯(cuò)誤棧信息的缺點(diǎn)讓很多開發(fā)者非常不滿,雖然第三方庫或多或少的彌補(bǔ)了這個(gè)缺點(diǎn),但是作為開發(fā)中占比非常大的一部分代碼,官方庫的缺乏支持還是令人不滿。所以Go team在1.13版本中進(jìn)一步完善了錯(cuò)誤相關(guān)的官方庫支持。
首先,提供了%w構(gòu)造方法和errors.Unwrap的方法對來支持類似Wrap和Cause相關(guān)的能力。

// 為錯(cuò)誤提供更豐富的上下文信息,方便定位錯(cuò)誤
if _, err := ioutil.ReadAll(r);err != nil {
        return fmt.Errorf("read file failed with err:%w", err)
}

// 判斷錯(cuò)誤的根錯(cuò)誤是什么,根據(jù)最初的錯(cuò)誤類型判斷需要走什么錯(cuò)誤處理邏輯
rawErr := errors.Unwrap(err)

不僅如此,官方庫還帶來了兩個(gè)錯(cuò)誤比較相關(guān)的API:

if errors.Is(err, io.EOF){
    ...
}

var eof io.EOF
if errors.As(err, &eof){
    ...
}

其中,errors.Is方法會逐層調(diào)用Unwrap方法,去和目標(biāo) err做比較,知道沒有Unwrap方法或者err比較成功。errors.As方法的作用類似于之前的針對錯(cuò)誤的類型斷言。
至此,golang官方庫提供了錯(cuò)誤的構(gòu)造方法,錯(cuò)誤的比較方法,額外信息包裝的能力,總體來說應(yīng)該算是比較完善了。
關(guān)于Go1.13錯(cuò)誤處理相關(guān)的實(shí)現(xiàn),可以參考。

夭折的try

另外一個(gè)小小的番外插曲,曾經(jīng)有一個(gè)呼聲頗高的錯(cuò)誤處理相關(guān)的提案:引入try關(guān)鍵字來增強(qiáng)錯(cuò)誤處理的能力。主要使用方法如下:

// 包裝調(diào)用方法
readFile := try(ioutil.ReadAll(r))
...
// 函數(shù)層級統(tǒng)一
defer func(){
    if err!=nil{
        switch err.(type){
            ...
        }  
    }
}()

帶來的便利是減少了大量的if err!=nil語句,提供函數(shù)層級的統(tǒng)一錯(cuò)誤處理處(一般在defer處)。然而最后由于可讀性和顯式處理錯(cuò)誤的種種原因,這個(gè)提案被拒絕了。
更近一步的信息可以參考github上相關(guān)的討論 和設(shè)計(jì)文檔。

實(shí)踐

基于go1.13提出的現(xiàn)有錯(cuò)誤處理工具,我們大概能夠采用下面的實(shí)踐來進(jìn)行錯(cuò)誤處理:

  1. 針對基礎(chǔ)錯(cuò)誤類型,一般通過直接聲明變量或者自定義結(jié)構(gòu):
// 常規(guī)的無額外參數(shù)的error
var BasicErr1 = errors.New("this is a basic error.")

func fn() error{
    ...
    if conditionA{
        return BasicErr
    }
}

// 調(diào)用處
if err!=nil{
    if errors.Is(err, BasicErr1){
        ...
    }
}

// 帶參數(shù)信息的錯(cuò)誤
type CustomErr struct {
    Code int64
    Msg string
}

func (e CustomErr)Error() string{
    return fmt.Sprintf("%d:%s", e.Code, e.Msg)
}

func fn() error{
    ...
    if conditionA{
        return CustomErr{Code: 123, Msg: "test"}
    }
}

// 調(diào)用處
if err!=nil{
    if e,ok:=err.(CustomErr);ok{
        ...
    }
}
  1. 對于調(diào)用三方庫獲取的報(bào)錯(cuò),一般將額外信息(比如調(diào)用參數(shù),上下文信息等方便定位問題的信息)包裝之后向上層調(diào)用方直接拋出:
if _,err:=ioutil.ReadAll(r);err!=nil{
    return fmt.Errorf("read file failed:%w", err)
}

// 調(diào)用方
if err!=nil{
    if errors.Is(err, io.EOF){
        ...
    }
}

關(guān)于錯(cuò)誤日志的處理部分,為了防止處處打日志造成的上下文信息分散和大量信息冗余,一般建議的處理方式是對于內(nèi)部方法的調(diào)用,使用%w包裝錯(cuò)誤和必要的額外信息,直接返回到上層;對于最外層方法(一般是http handler或者rpc handler),將錯(cuò)誤包裝上下文,打印到錯(cuò)誤日志中,再使用errors.Is或者errors.As方法,根據(jù)錯(cuò)誤類型進(jìn)行不同的錯(cuò)誤處理邏輯。這樣的好處是,對于全局而言,有且只有最外層一份錯(cuò)誤日志,而這個(gè)錯(cuò)誤信息時(shí)包裝了層層調(diào)用信息的,內(nèi)容最為齊全。

分享到:
標(biāo)簽:Golang
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定