在使用 gin
開發接口的時候,返回接口數據是這樣寫的。json
type response struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } // always return http.StatusOK c.JSON(http.StatusOK, response{ Code: 20101, Msg: "用戶手機號不合法", Data: nil, })
這種寫法 code
、msg
都是在哪須要返回在哪定義,沒有進行統一管理。編碼
// 好比,返回「用戶手機號不合法」錯誤 c.JSON(http.StatusOK, errno.ErrUserPhone.WithID(c.GetString("trace-id"))) // 正確返回 c.JSON(http.StatusOK, errno.OK.WithData(data).WithID(c.GetString("trace-id")))
errno.ErrUserPhone
、errno.OK
表示自定義的錯誤碼,下面會看到定義的地方。code
.WithID()
設置當前請求的惟一ID,也能夠理解爲鏈路ID,忽略也能夠。接口
.WithData()
設置成功時返回的數據。開發
下面分享下編寫的 errno
包源碼,很是簡單,但願你們不要介意。源碼
// errno/errno.go package errno import ( "encoding/json" ) var _ Error = (*err)(nil) type Error interface { // i 爲了不被其餘包實現 i() // WithData 設置成功時返回的數據 WithData(data interface{}) Error // WithID 設置當前請求的惟一ID WithID(id string) Error // ToString 返回 JSON 格式的錯誤詳情 ToString() string } type err struct { Code int `json:"code"` // 業務編碼 Msg string `json:"msg"` // 錯誤描述 Data interface{} `json:"data"` // 成功時返回的數據 ID string `json:"id,omitempty"` // 當前請求的惟一ID,便於問題定位,忽略也能夠 } func NewError(code int, msg string) Error { return &err{ Code: code, Msg: msg, Data: nil, } } func (e *err) i() {} func (e *err) WithData(data interface{}) Error { e.Data = data return e } func (e *err) WithID(id string) Error { e.ID = id return e } // ToString 返回 JSON 格式的錯誤詳情 func (e *err) ToString() string { err := &struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` ID string `json:"id,omitempty"` }{ Code: e.Code, Msg: e.Msg, Data: e.Data, ID: e.ID, } raw, _ := json.Marshal(err) return string(raw) }
// errno/code.go package errno var ( // OK OK = NewError(0, "OK") // 服務級錯誤碼 ErrServer = NewError(10001, "服務異常,請聯繫管理員") ErrParam = NewError(10002, "參數有誤") ErrSignParam = NewError(10003, "簽名參數有誤") // 模塊級錯誤碼 - 用戶模塊 ErrUserPhone = NewError(20101, "用戶手機號不合法") ErrUserCaptcha = NewError(20102, "用戶驗證碼有誤") // ... )
code.go
文件中定義。1 | 01 | 01 |
---|---|---|
服務級錯誤碼 | 模塊級錯誤碼 | 具體錯誤碼 |