無論在什麼系統中, 定義錯誤碼都是必不可少的.git
錯誤碼能夠幫助定義問題, 一般錯誤碼設計爲某種模式結構,
能夠判斷出錯誤的級別, 錯誤的模塊和具體錯誤信息.github
一個良好結構的錯誤碼有助於簡化問題描述,
當前設計的錯誤碼共有五位, 結構以下:web
1 | 00 | 01 |
---|---|---|
服務級別 | 模塊 | 具體錯誤 |
第一位是服務級別, 1 爲系統錯誤, 2 爲普通錯誤.數據庫
第二三位是模塊, 模塊不是指 Go 中的模塊, 而是指代某個範圍, 好比數據庫錯誤, 認證錯誤.服務器
第四五位是具體錯誤, 好比數據庫錯誤中的插入錯誤, 找不到數據等.數據結構
定義錯誤碼的時候不光有 Code 數字, 也會有對應的文本信息, 一般, 文本分爲兩類,
一類是給用戶看的, 另外一類是用於 debug 的.函數
在 pkg 目錄下新建一個 errno 目錄, 並建立相應的模塊.加密
package errno import "fmt" // 定義錯誤碼 type Errno struct { Code int Message string } func (err Errno) Error() string { return err.Message } // 定義錯誤 type Err struct { Code int // 錯誤碼 Message string // 展現給用戶看的 Errord error // 保存內部錯誤信息 } func (err *Err) Error() string { return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Errord) }
上面定義了兩種數據結構, 每一種都實現了 Error() 方法, 也就是繼承了 error 接口.debug
Errno 定義了錯誤碼的結構, 會在另外一個文件中統必定義全部的錯誤碼.
Err 定義了完整的錯誤的結構, 一般能夠理解爲 Errno 和一個內部錯誤的結合.設計
// 使用 錯誤碼 和 error 建立新的 錯誤 func New(errno *Errno, err error) *Err { return &Err{ Code: errno.Code, Message: errno.Message, Errord: err, } }
New 函數從一個 Errno 和 error 中返回新的 Err, 這樣就包裝了內部錯誤.
另外一個重要的方法是解碼錯誤, 獲取 Code 和 Message.
// 解碼錯誤, 獲取 Code 和 Message func DecodeErr(err error) (int, string) { if err == nil { return OK.Code, OK.Message } switch typed := err.(type) { case *Err: if typed.Code == ErrBind.Code { typed.Message = typed.Message + " 具體是 " + typed.Errord.Error() } return typed.Code, typed.Message case *Errno: return typed.Code, typed.Message default: } return InternalServerError.Code, err.Error() }
在設計完成 errno 模塊以後, 咱們須要定義一些常見的錯誤碼.
package errno /* 錯誤碼設計 第一位表示錯誤級別, 1 爲系統錯誤, 2 爲普通錯誤 第二三位表示服務模塊代碼 第四五位表示具體錯誤代碼 */ var ( OK = &Errno{Code: 0, Message: "OK"} // 系統錯誤, 前綴爲 100 InternalServerError = &Errno{Code: 10001, Message: "內部服務器錯誤"} ErrBind = &Errno{Code: 10002, Message: "請求參數錯誤"} ErrTokenSign = &Errno{Code: 10003, Message: "簽名 jwt 時發生錯誤"} ErrEncrypt = &Errno{Code: 10004, Message: "加密用戶密碼時發生錯誤"} // 數據庫錯誤, 前綴爲 201 ErrDatabase = &Errno{Code: 20100, Message: "數據庫錯誤"} ErrFill = &Errno{Code: 20101, Message: "從數據庫填充 struct 時發生錯誤"} // 認證錯誤, 前綴是 202 ErrValidation = &Errno{Code: 20201, Message: "驗證失敗"} ErrTokenInvalid = &Errno{Code: 20202, Message: "jwt 是無效的"} // 用戶錯誤, 前綴爲 203 ErrUserNotFound = &Errno{Code: 20301, Message: "用戶沒找到"} ErrPasswordIncorrect = &Errno{Code: 20302, Message: "密碼錯誤"} )
錯誤碼是 API 服務中不可缺乏的一環, 但錯誤碼的結構設計倒是千差萬別,
這個時候仍是要多參考一些大廠的開放 API 設計, 找出共性, 去粗取精.
做爲版本 v0.5.0
說明, 當前分支下定義的錯誤碼和上文中顯示的不同, 仍是以文章爲主,由於寫文章也是一個思考的過程, 因此有時會對代碼作一點改動.