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

Go項目分層下的最佳error處理方式分享

 更新時間:2023年06月21日 08:26:34   作者:陳明勇  
這篇文章主要來和大家一起探討?Go?項目分層下的最佳?error?處理方式,準備好了嗎?準備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧

前言

Go 語言中,對于程序中可能出現(xiàn)的問題,比如數(shù)據庫連接失敗,文件讀取錯誤等,都是使用基于內置的 error 接口類型的值來表示和處理錯誤。而在分層的項目中,如何最佳處理 error成為眾多人關注的問題,本文將探討 Go 項目分層下的最佳 error 處理方式。準備好了嗎?準備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧。

常見分層下的 error 處理

以典型的 MVC ( daoservicecontroller/middleware) 分層結構舉例,常見的錯誤處理大致如下:

// controller / middleware
res, err := service.GetById(ctx, id)
if err != nil {
    log.Errorf(ctx, "service.GetById failed, id=%s, error=%v", err)
    ······
}
······
// service  
article, err := dao.GetById(ctx, id)
if err != nil {
    log.Errorf(ctx, fmt.Errorf("dao.GetById failed, error=%v", err))
    return fmt.Errorf("dao.GetById failed, error=%v", err)
}
······
// dao
······
if err != nil {
    log.Errorf(ctx, fmt.Errorf("GetById failed, id=%s, error=%v", id, err))
    return fmt.Errorf("GetById failed, id=%s, error=%v", id, err)
}
······

以上錯誤處理的方式,在每一層都打印一條錯誤日志,然后對得到的 error 進行二次封裝。雖然以上處理方式可以使我們在查看日志時方便故障排查和問題定位,同時提供了錯誤的上下文信息,但也存在以下問題:

  • 每層都打印日志,帶來了大量日志;
  • 字符串拼接費時費力,缺乏統(tǒng)一規(guī)范,可能導致理解困難;
  • 通過字符串拼接,獲得新 error,破壞了原始 error,會導致等值判定失敗,難以獲取詳細的堆棧關聯(lián)。

分層下的最佳 error 處理方式

遵循以下建議,我們可以更好地處理 error

  • 1、一個 error,應該只被處理一次
  • 2、讓 error 包含更多的信息
  • 3、原始 error,應保證完整性,不被破壞
  • 4、error 需要被日志記錄

什么意思呢?為了確保 error 處理的有效性,對于某一層來說,應該保證每個錯誤只被處理一次,要么打印 error 信息,要么將其傳遞給上一層,而不是每一層都獨立打印 error 信息。

同時,在傳遞錯誤給上一層時,應該附帶有用的額外信息,并確保不破壞原始錯誤的完整性,以保證錯誤的可追溯性。最后,通過記錄錯誤日志可以幫助我們進行問題排查。

如圖所示:

Dao 層遇到原始錯誤 Original Error 后,我們可以將其與需要的額外信息封裝,組成一個新的 error ,然后傳遞給上一層,逐層附加信息,直至傳遞到 controller 層,最終得到一個全新的 error,其中包含 Original error 和每一層添加的額外信息。

通過最終得到的這個 error,我們可以像剝洋蔥一樣逐層解開,追溯到 Original error ,并獲取我們所需的信息。如果 controller 是最頂層,我們可以打印完整的錯誤信息,然后獲取 Original Error,并打印其所包含的 堆棧信息

Wrap error

盡管前面已經探討了分層下的最佳 error 處理方式,但我們會發(fā)現(xiàn)官方標準庫errors 所提供的函數(shù)并不能滿足我們的需求,我們不能借助現(xiàn)有函數(shù)對原始錯誤附加額外信息且不破壞其完整性。在這種情況下,我們可以借助第三方庫 github.com/pkg/errors 來完成我們的需求。

github.com/pkg/errors 提供了很多實用的函數(shù),例如:

  • Wrap(err error, message string) error:該函數(shù)基于原始錯誤 err,返回一個帶有堆棧跟蹤信息和附加信息 message 的新 error
  • Wrapf(err error, format string, args ...interface{}) error: 和上面的函數(shù)功能是一樣的,只不過可以對附加信息進行格式化封裝
  • WithMessage(err error, message string) error:該函數(shù)基于原始錯誤 err,返回一個附加信息 message 的新 error
  • WithMessagef(err error, format string, args ...interface{}) error: 和上面的函數(shù)功能是一樣的,只不過可以對附加信息進行格式化封裝
  • Cause(err error) error:該函數(shù)用于提取 err 中的原始 error,它會遞歸地檢查 error,直到找到最底層的原始 error,如果存在的話

了解了以上函數(shù)的功能,我們來看看項目分層下最佳 error 的具體實現(xiàn)。

// controller / middleware  
res, err := service.GetById(ctx, id)  
if err != nil {  
  log.Errorf(ctx, "service.GetById failed, original error: %T %v", errors.Cause(err), errors.Cause(err))  
  log.Errorf(ctx, "stack trace: \n%+v\n", err)  
······  
}  
······  
// service  
article, err := dao.GetById(ctx, id)  
if err != nil {  
  return errors.WithMessage(err, "dao.GetById failed")  
}  
······  
// dao  
······  
if err != nil {  
  return errors.Wrapf(err, "GetById failed, id=%s, error=%v", id, err)  
}  
······

當在 Dao 層遇到原始錯誤 Original Error 后,使用 errors.Wrap() 對錯誤進行封裝。這個封裝操作可以在保留根因(Origin error)的同時,提供堆棧信息,并添加額外的上下文信息,然后將封裝后的錯誤傳遞給上一層處理。

service 層接收到 error 之后,使用 errors.WithMessage() 函數(shù),將額外的信息附加到錯誤上,并繼續(xù)將錯誤向上層傳遞,直至到達 controller 層。在 controller 層,我們可以打印出根因的類型、信息以及堆棧信息,以便更好地進行問題排查。

小結

本文對 Go 項目分層下的最佳 error 處理方式進行介紹,并通過使用 github.com/pkg/errors 庫中的一些實用函數(shù)來提供實現(xiàn)示例。

盡管本文基于 MVC 分層結構進行介紹,但實際上大多數(shù)項目的分層結構可能各不相同,因此在確定錯誤處理方式和策略時需要考慮具體情況。然而,我相信通過參考本文提出的四點建議和實現(xiàn)示例或其他更好的建議,一定能夠確定最佳的錯誤處理方式。

到此這篇關于Go項目分層下的最佳error處理方式分享的文章就介紹到這了,更多相關Go error處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • go select編譯期的優(yōu)化處理邏輯使用場景分析

    go select編譯期的優(yōu)化處理邏輯使用場景分析

    select 是 Go 中的一個控制結構,類似于用于通信的 switch 語句。每個 case 必須是一個通信操作,要么是發(fā)送要么是接收。接下來通過本文給大家介紹go select編譯期的優(yōu)化處理邏輯使用場景分析,感興趣的朋友一起看看吧
    2021-06-06
  • go語言基于Session和Redis實現(xiàn)短信驗證碼登錄

    go語言基于Session和Redis實現(xiàn)短信驗證碼登錄

    本文介紹了go語言基于Session和Redis實現(xiàn)短信驗證碼登錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-11-11
  • Golang使用Gin創(chuàng)建Restful API的實現(xiàn)

    Golang使用Gin創(chuàng)建Restful API的實現(xiàn)

    本文主要介紹了Golang使用Gin創(chuàng)建Restful API的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Golang中函數(shù)(Function)和方法(Method)的區(qū)別詳解

    Golang中函數(shù)(Function)和方法(Method)的區(qū)別詳解

    在Golang中,大家必然會頻繁使用到函數(shù)(Function)和方法(Method),但是有的同學可能并沒有注意過函數(shù)和方法的異同點,函數(shù)和方法都是用來執(zhí)行特定任務的代碼塊,雖然很相似,但也有很大的區(qū)別,所以本文將詳細講解函數(shù)和方法的定義以及它們的異同點
    2023-07-07
  • go gin中間件關于 c.next()、c.abort()和return的使用小結

    go gin中間件關于 c.next()、c.abort()和return的使用小結

    中間件的執(zhí)行順序是按照注冊順序執(zhí)行的,中間件可以通過 c.abort() + retrurn 來中止當前中間件,后續(xù)中間件和處理器的處理流程,?這篇文章給大家介紹go gin中間件關于 c.next()、c.abort()和return的使用小結,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Go正則表達式匹配字符串,替換字符串方式

    Go正則表達式匹配字符串,替換字符串方式

    介紹了Go語言中使用正則表達式進行字符串匹配和替換的方法,包括匹配單個子字符串和所有子字符串,個人經驗分享,旨在為讀者提供實用的編程技巧,并鼓勵大家支持腳本之家
    2025-02-02
  • Go語言中的格式化輸出占位符的用法詳解

    Go語言中的格式化輸出占位符的用法詳解

    在 Go 語言中,格式化輸出是一個非常常用的功能,特別是在處理字符串、數(shù)字和其他數(shù)據類型時,本文將詳細介紹 Go 語言中常用的格式化占位符及其用法,希望對大家有所幫助
    2024-10-10
  • 利用Go實現(xiàn)一個簡易DAG服務的示例代碼

    利用Go實現(xiàn)一個簡易DAG服務的示例代碼

    DAG的全稱是Directed Acyclic Graph,即有向無環(huán)圖,DAG廣泛應用于表示具有方向性依賴關系的數(shù)據,如任務調度、數(shù)據處理流程、項目管理以及許多其他領域,下面,我將用Go語言示范如何實現(xiàn)一個簡單的DAG服務,需要的朋友可以參考下
    2024-03-03
  • 深入探究Go語言的錯誤策略與異常機制

    深入探究Go語言的錯誤策略與異常機制

    本文深入探討了Go語言的錯誤策略與異常機制,主要介紹了錯誤處理的重要性,以及Go語言中的錯誤類型和處理函數(shù),此外還討論了Go語言的異常機制,包括panic和recover函數(shù)的使用,需要的朋友可以參考下
    2024-02-02
  • Golang并發(fā)繞不開的重要組件之Goroutine詳解

    Golang并發(fā)繞不開的重要組件之Goroutine詳解

    Goroutine、Channel、Context、Sync都是Golang并發(fā)編程中的幾個重要組件,這篇文中主要為大家介紹了Goroutine的相關知識,需要的可以參考一下
    2023-06-06

最新評論

花莲市| 汶川县| 赫章县| 深泽县| 时尚| 全椒县| 彰化市| 泽州县| 进贤县| 建德市| 寻乌县| 肇源县| 镇江市| 土默特右旗| 卢龙县| 囊谦县| 灌阳县| 麻江县| 潍坊市| 安图县| 富民县| 南通市| 报价| 会东县| 新邵县| 南安市| 荃湾区| 开江县| 额济纳旗| 尖扎县| 白朗县| 东源县| 任丘市| 炎陵县| 静海县| 上饶市| 永靖县| 海盐县| 广东省| 沧州市| 行唐县|