偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Go項目實戰(zhàn)-讓自定義Error支持Go的errors.Is判定以及原型模式的應(yīng)用

開發(fā) 項目管理
關(guān)于項目自定義Error的優(yōu)化,在課程中我還使用了這里使用設(shè)計模式里的原型模式, 把項目預(yù)定義的全局錯誤都是當(dāng)作原型-prototype,保證我們既能規(guī)范管理我們項目的錯誤碼,也能更自由放心地在程序中使用它們。?

經(jīng)過前面三節(jié)高代碼強度的學(xué)習(xí),相信大家都已經(jīng)有點累了,本節(jié)我們不著急繼續(xù)“趕路”,休息片刻!我們換個輕松點的話題,聊一聊咱們項目定制化Error--AppError 怎么支持Go語言的 errors.Is 判定,以及項目預(yù)定義的那些Error在實際使用過程中某些情況下會出現(xiàn)循環(huán)引用的問題,我們會利用一個原型設(shè)計模式來解決這個問題。

圖片

項目定制化Error 回顧

在定義項目 Error 實現(xiàn)錯誤鏈和發(fā)生位置記錄這篇文章中我們給項目定義了自己的Error類型 AppError

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

目的是為了通過自己的封裝讓Go的Error能支持錯誤原因和發(fā)生位置的記錄。同時我們還為項目的開發(fā)預(yù)定義了很多Error變量。

// 用戶模塊相關(guān)錯誤碼 10000100 ~ 1000199
var (
 ErrUserInvalid      = newError(10000101, "用戶異常")
 ErrUserNameOccupied = newError(10000102, "用戶名已被占用")
 ErrUserNotRight     = newError(10000103, "用戶名或密碼不正確")
)
// 商品模塊相關(guān)錯誤碼 10000200 ~ 1000299
var (
 ErrCommodityNotExists = newError(10000200, "商品不存在")
 ErrCommodityStockOut  = newError(10000201, "庫存不足")
)
// 購物車模塊相關(guān)錯誤碼 10000300 ~ 1000399
var (
 ErrCartItemParam = newError(10000300, "購物項參數(shù)異常")
 ErrCartWrongUser = newError(10000301, "用戶購物信息不匹配")
)

在 Go項目Error的統(tǒng)一管理和處理建議 中我建議需要返回給客戶端返回約定好的錯誤碼的錯誤都在這里預(yù)先定義。而對于一些像DB、存儲之類錯誤產(chǎn)生的Error 無需告知客戶端明確原因只需要讓客戶端發(fā)生了服務(wù)端內(nèi)部錯誤的情況、或者不知道怎么處理的底層錯誤,我們先統(tǒng)一用Wrap方法把它包裝成應(yīng)用的AppError。

err = DBMaster().WithContext(ud.ctx).Create(userModel).Error
if err != nil {
    err = errcode.Wrap("UserDaoCreateUserError", err)
    return nil, err
}

在設(shè)計的過程中,覺得已經(jīng)夠全面了,但是只要真正把它來開發(fā)需求時,還是能發(fā)現(xiàn)有問題的,具體什么問題呢? 我們繼續(xù)往下看。

怎么讓自定義Error支持Go的errors.Is判定

想讓Error支持Go的errors.Is 判定,我們先來看看errors.Is 方法里到底是怎么判定Error是不是給定的目標(biāo)錯誤的,其源碼如下:

func Is(err, target error) bool {
 if target == nil {
  return err == target
 }

 isComparable := reflectlite.TypeOf(target).Comparable()
 for {
  if isComparable && err == target {
   return true
  }
  if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
   return true
  }
  if err = Unwrap(err); err == nil {
   return false
  }
 }
}

其源碼中邏輯是會一層層地解包error,每層的error都去看看是否已經(jīng)實現(xiàn)了 interface{ Is(error) bool } 這個接口,如果實現(xiàn)了調(diào)用該層error的Is方法進行判定,如果跟給定error不相等或者沒有實現(xiàn)Is接口,則繼續(xù)用Uwrap解包,解到不能解為止 (err == nil)。

所以這里給我們預(yù)留了兩個接口,我們讓AppError實現(xiàn) Is 和 Uwrap 方法后,它也就支持Go的 errors.Is 判定啦。

下面我們在 common/errcode/error.go 中加入這兩個方法的實現(xiàn)。

package errcode

func (e *AppError) UnWrap() error {
 return e.cause
}

// Is 與上面的UnWrap一起讓 *AppError 支持 errors.Is(err, target)
func (e *AppError) Is(target error) bool {
 targetErr, ok := target.(*AppError)
 if !ok {
  return false
 }
 return targetErr.Code() == e.Code()
}

關(guān)于項目自定義Error的優(yōu)化,在課程中我還使用了這里使用設(shè)計模式里的原型模式, 把項目預(yù)定義的全局錯誤都是當(dāng)作原型-prototype,保證我們既能規(guī)范管理我們項目的錯誤碼,也能更自由放心地在程序中使用它們。

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

2022-09-21 08:47:05

項目多線程對象

2023-06-19 08:49:55

go文件管理

2020-10-21 14:29:15

原型模式

2021-05-18 08:52:31

Prototype 原型模式設(shè)計模式

2021-10-28 19:09:09

模式原型Java

2022-05-30 08:14:48

編譯器Go語言

2013-11-26 17:00:08

Android設(shè)計模式

2021-09-08 09:41:09

開發(fā)Go代碼

2015-06-08 09:05:10

Java原型模式

2025-06-10 09:07:32

Go模式開發(fā)

2024-11-13 09:13:45

2011-05-27 09:51:44

Windows Pho應(yīng)用商店

2022-11-06 23:17:23

Go語言項目

2024-08-09 10:59:01

KubernetesSidecar模式

2024-12-27 15:10:16

設(shè)計模式原型模式場景

2023-03-13 00:10:46

Go語言版本

2021-06-07 09:51:22

原型模式序列化

2016-08-18 13:56:33

AndroidExecutorsubmit

2025-04-28 01:55:00

工具sqlmockSQL

2025-03-07 09:01:14

商品模塊接口項目
點贊
收藏

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