成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

學(xué)會(huì)定制化 Go 項(xiàng)目的 error,回溯錯(cuò)誤的原因和發(fā)生位置

開(kāi)發(fā) 前端
如果你們的研發(fā)習(xí)慣是請(qǐng)求接口的響應(yīng)一律是 HTTP 200 再通過(guò)相應(yīng)里的code碼判斷是否正確,這個(gè)方法可以放著不用, 規(guī)范化一點(diǎn)肯定是這種比較好,況且HTTP Status 不是 200 狀態(tài)碼,也是可以返回 code msg 那些信息給客戶端的。

Go語(yǔ)言的Error處理一直被人吐槽,吐槽的點(diǎn)除了一個(gè)接一個(gè)的 if err != nil 的判斷外,還有人說(shuō)Go的錯(cuò)誤太原始不能像其他語(yǔ)言那樣在拋出異常的時(shí)候的時(shí)候傳一個(gè)Casue Exception 把導(dǎo)致異常的整個(gè)原因鏈串起來(lái)。

第一點(diǎn)確實(shí)是事實(shí),但是寫(xiě)習(xí)慣了也能接受,而且對(duì)新手友好。第二點(diǎn)屬實(shí)就有點(diǎn)尬黑了。

用Go開(kāi)發(fā)項(xiàng)目時(shí)想讓程序拋出的 error 信息不要那么單薄,需要自己搭建項(xiàng)目時(shí)先做一番基礎(chǔ)工作,自己定義項(xiàng)目的Error類型在包裝錯(cuò)誤的時(shí)候記錄上錯(cuò)誤的原因和發(fā)生的位置,比如像下面這樣。

{
    "code": 10000000,
    "msg": "服務(wù)器內(nèi)部錯(cuò)誤",
    "cause": "db error: undefined column user_id",
    "occurred": "go-study-lab/go-mall.TestAppError, file: building.go, line: 69"
}

同時(shí)它還要實(shí)現(xiàn)Go的error interface,能融入Go 的錯(cuò)誤處理機(jī)制才行。

今天我就帶大家通過(guò)自定義項(xiàng)目Error并實(shí)現(xiàn) Go error interface ,讓你的Go項(xiàng)目Error擁有更豐富的錯(cuò)誤原因和發(fā)生位置的信息。看到一個(gè)錯(cuò)誤能看出來(lái)時(shí)什么原因?qū)е碌摹⒁约笆悄牡拇a導(dǎo)致的這樣能大大降低Go項(xiàng)目的維護(hù)難度。

Go Error 定制化Go Error 定制化

定義項(xiàng)目的Error結(jié)構(gòu)

首先我們?cè)陧?xiàng)目的common目錄中增加errcode目錄,該目錄下會(huì)創(chuàng)建兩個(gè)文件error.go 和 code.go。error.go文件用來(lái)存放自定義Error的結(jié)構(gòu)和相關(guān)方法,code.go 用來(lái)放置項(xiàng)目各種預(yù)定義的Error。

.
|-- common
|   |-- errcode
|       |---code.go
|       |---error.go
|-- main.go
|-- go.mod
|-- go.sum

我們現(xiàn)在error.go 中定義AppError

type AppError struct {
 code     int    `json:"code"`
 msg      string `json:"msg"`
 cause    error  `json:"cause"`
}

cause 字段保存的是導(dǎo)致產(chǎn)生 AppErr 的原因,比如一個(gè)數(shù)據(jù)庫(kù)查詢語(yǔ)法錯(cuò)誤,拿它再來(lái)生成項(xiàng)目的 AppError 或者是給預(yù)定義好的 AppError 追加上這個(gè)原因的error, 這樣就能達(dá)到保存錯(cuò)誤鏈條的目的。

現(xiàn)在AppError 還不是 error 類型,需要讓他實(shí)現(xiàn)Go的 error interface,這個(gè)接口如下。

type error interface {
 Error() string
}

其中只定義了一個(gè)方法,我們讓AppError實(shí)現(xiàn)Error方法把它變成 error 類型。

func (e *AppError) Error() string {
 if e == nil {
  return ""
 }

 formattedErr := struct {
  Code     int    `json:"code"`
  Msg      string `json:"msg"`
  Cause    string `json:"cause"`
 }{
  Code:     e.Code(),
  Msg:      e.Msg(),
 }

 if e.cause != nil {
  formattedErr.Cause = e.cause.Error()
 }
 errByte, _ := json.Marshal(formattedErr)
 return string(errByte)
}

Error方法返回的是AppError對(duì)象的JSON序列化字符串,其中如果cause字段不為空即錯(cuò)誤原因不為空,再去錯(cuò)誤原因的Error方法拿到底層的錯(cuò)誤信息。

我們把Stringer 接口也實(shí)現(xiàn)一下,在沒(méi)有類型字段轉(zhuǎn)換的地方,它還是*AppErr類型,保證這個(gè)時(shí)候序列化它的時(shí)候仍然能得到期望的信息。

func (e *AppError) String() string {
 return e.Error()
}

接下來(lái)我們?cè)赾ode.go 中先預(yù)定義一些基礎(chǔ)的錯(cuò)誤

var (
 Success            = newError(0, "success")
 ErrServer          = newError(10000000, "服務(wù)器內(nèi)部錯(cuò)誤")
 ErrParams          = newError(10000001, "參數(shù)錯(cuò)誤, 請(qǐng)檢查")
 ErrNotFound        = newError(10000002, "資源未找到")
 ErrPanic           = newError(10000003, "(*^__^*)系統(tǒng)開(kāi)小差了,請(qǐng)稍后重試") // 無(wú)預(yù)期的panic錯(cuò)誤
 ErrToken           = newError(10000004, "Token無(wú)效")
 ErrForbidden       = newError(10000005, "未授權(quán)") // 訪問(wèn)一些未授權(quán)的資源時(shí)的錯(cuò)誤
 ErrTooManyRequests = newError(10000006, "請(qǐng)求過(guò)多")
)

上面大家看到了 AppError 的類型定義中,字段的訪問(wèn)性都是包內(nèi)可訪問(wèn)的,所以我們要定義一些 getter 方法,這樣接口返回錯(cuò)誤響應(yīng)時(shí),才能讀到錯(cuò)誤碼和錯(cuò)誤信息。

func (e *AppError) Code() int {
 return e.code
}

func (e *AppError) Msg() string {
 return e.msg
}

func (e *AppError) HttpStatusCode() int {
 switch e.Code() {
 case Success.Code():
  return http.StatusOK
 case ErrServer.Code(), ErrPanic.Code():
  return http.StatusInternalServerError
 case ErrParams.Code():
  return http.StatusBadRequest
 case ErrNotFound.Code():
  return http.StatusNotFound
 case ErrTooManyRequests.Code():
  return http.StatusTooManyRequests
 case ErrToken.Code():
  return http.StatusUnauthorized
 case ErrForbidden.Code():
  return http.StatusForbidden
 default:
  return http.StatusInternalServerError
 }
}

這里的 HttpStatusCode 返回的是HTTP 狀態(tài)碼,如果你們的研發(fā)習(xí)慣是請(qǐng)求接口的響應(yīng)一律是 HTTP 200 再通過(guò)相應(yīng)里的code碼判斷是否正確,這個(gè)方法可以放著不用, 規(guī)范化一點(diǎn)肯定是這種比較好,況且HTTP Status 不是 200 狀態(tài)碼,也是可以返回 code msg 那些信息給客戶端的。

底層Error怎么變成項(xiàng)目Error

上面我們預(yù)定義好了幾個(gè)應(yīng)用錯(cuò)誤,這里說(shuō)明一下,預(yù)定義好的錯(cuò)誤會(huì)最終返回給發(fā)起請(qǐng)求的客戶端,所以控制器層各個(gè)URI的路由處理控制器中最后一定要返回預(yù)定義的錯(cuò)誤,這個(gè)我們會(huì)在未來(lái)給Go項(xiàng)目封裝統(tǒng)一的響應(yīng)組件時(shí)處理。

那一個(gè)底層的錯(cuò)誤怎么才能變成我們自定義的錯(cuò)誤呢?

責(zé)任編輯:武曉燕 來(lái)源: 網(wǎng)管叨bi叨
相關(guān)推薦

2025-03-31 00:29:44

2024-10-30 09:29:30

Go項(xiàng)目Error

2022-11-09 11:50:21

2020-10-10 07:14:08

前端項(xiàng)目斷點(diǎn)

2024-12-17 09:14:48

項(xiàng)目http 庫(kù)API

2025-06-20 09:57:42

2022-07-19 08:01:55

函數(shù)Go格式化

2009-07-20 15:51:45

JDBC連接Oracl

2023-02-07 07:16:54

人工智能機(jī)器學(xué)習(xí)方法

2010-08-02 08:54:53

Flex模塊化

2020-08-07 11:46:47

JavaScript開(kāi)發(fā)代碼

2024-02-21 19:02:05

Go模板化方式

2021-01-25 10:30:52

數(shù)字化分析轉(zhuǎn)型首席執(zhí)行官

2025-05-15 09:05:19

Go項(xiàng)目BDD測(cè)試

2022-05-17 08:02:55

GoTryLock模式

2023-07-12 15:41:18

2023-09-07 07:53:21

JavaScriptGoRust

2018-06-12 15:55:44

數(shù)字化項(xiàng)目

2021-06-29 10:01:56

物聯(lián)網(wǎng)項(xiàng)目eSIM物聯(lián)網(wǎng)

2020-06-05 08:29:40

語(yǔ)言PythonGo
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品久久久久久久久久久久久久 | 色婷婷av99xx| a看片| 久久成人av | 日本久久一区二区三区 | 伊人网伊人网 | 欧美精品久久 | 欧美日韩一区二区三区四区五区 | 一本一道久久a久久精品综合 | 日日操夜夜操天天操 | 亚洲中午字幕 | 中文天堂在线一区 | 伊人一区 | 日韩国产在线 | 国产视频第一页 | 欧美激情视频一区二区三区在线播放 | 久久久久久久一区 | 国产小视频在线观看 | 国产精品久久久99 | 精品久久亚洲 | 日日夜夜免费精品视频 | 亚洲一区不卡在线 | 国产精品免费看 | 国产成人免费视频网站视频社区 | 成人久久久| 日韩精品中文字幕一区二区三区 | 久久精品亚洲 | 91高清免费 | 日韩中文字幕 | 欧美久久一区二区 | www久久爱 | 真人女人一级毛片免费播放 | 成人影院av | www.天天操.com | 97视频免费 | 手机三级电影 | 欧美成人精品一区二区三区 | 91精品国产91久久久久久密臀 | 精品区一区二区 | 国产精品久久久久久二区 | 国产成人a亚洲精品 |