大良營銷網(wǎng)站建設(shè)案例百度的競價排名是哪種方式
go-zero 錯誤處理(統(tǒng)一響應(yīng)信息)
在實現(xiàn)注冊邏輯時,嘗試重復(fù)注冊可能會返回 400 狀態(tài)碼,顯然不符合正常設(shè)計思維。我們希望狀態(tài)碼為 200,并在響應(yīng)中返回錯誤信息。
一、使用第三方庫
1.下載庫
目前 go-zero官方的 zeromicro 下有一個 x 倉庫,可以實現(xiàn)統(tǒng)一響應(yīng)格式,我們先安裝下:
go get github.com/zeromicro/x
它會自動幫我們把響應(yīng)信息改為下面這種格式:
{"code": 0,"msg": "ok","data": {...}
}
2.修改handler
接著我們修改internal/handler/register/registerhandler.go
文件,把原來的響應(yīng)處理,替換成這個庫的:
//導(dǎo)入zeromicro庫并設(shè)置別名,避免和原生的http沖突
import (xhttp "github.com/zeromicro/x/http"
)//修改RegisterHandler的返回信息
func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {var req types.RegisterRequestif err := httpx.Parse(r, &req); err != nil {//使用xhttp.JsonBaseResponseCtx 替換掉httpx.ErrorCtxxhttp.JsonBaseResponseCtx(r.Context(), w, err)//httpx.ErrorCtx(r.Context(), w, err)return}l := register.NewRegisterLogic(r.Context(), svcCtx)resp, err := l.Register(&req)if err != nil {//使用xhttp.JsonBaseResponseCtx 替換掉httpx.ErrorCtxxhttp.JsonBaseResponseCtx(r.Context(), w, err)//httpx.ErrorCtx(r.Context(), w, err)} else {//使用xhttp.JsonBaseResponseCtx 替換掉httpx.OkJsonCtxxhttp.JsonBaseResponseCtx(r.Context(), w, resp)//httpx.OkJsonCtx(r.Context(), w, resp)}}
}
3.修改返回錯誤
在internal/logic/user/registerlogic.go
文件中,把原來的err
修改成 errors.New()
,它的參數(shù)有兩個,一個是用來返回 code碼 ,還有一個是message消息:
func (l *RegisterLogic) Register(req *types.RegisterRequest) (resp *types.RegisterResponse, err error) {// todo: add your logic here and delete this line/*.....*/if user != nil {//return nil, errreturn nil, errors.New(1, "用戶已注冊")}//插入新的數(shù)據(jù)/*.....*/if err != nil {//return nil, errreturn nil, errors.New(2, "用戶注冊失敗")}}
接著我們運行項目,使用Postman重新測試,結(jié)果如下:
二、自定義錯誤管理
如果你不想使用這個庫,或者想自己實現(xiàn)一些自定義錯誤,那么你也可以自己設(shè)置錯誤管理
1.自定義錯誤結(jié)構(gòu)與格式化
我們在internal
目錄下新建biz
目錄,用于業(yè)務(wù)處理,然后再這個目錄下分別創(chuàng)建3個文件
創(chuàng)建biz.go
文件
package biztype Error struct {Code int `json:"code"`Msg string `json:"msg"`
}func NewError(code int, msg string) *Error {return &Error{Code: code,Msg: msg,}
}func (e *Error) Error() string {return e.Msg
}
創(chuàng)建resp.go
文件
package biztype Result struct {Code int `json:"code"`Msg string `json:"msg"`Data any `json:"data"`
}func Success(data any) *Result {return &Result{Code: Ok,Msg: "success",Data: data,}
}func Fail(err *Error) *Result {return &Result{Code: err.Code,Msg: err.Msg,}
}
創(chuàng)建vars.go
文件
package bizconst Ok = 200var (AlreadyRegister = NewError(1, "用戶已注冊")PasswordErr = NewError(2, "密碼錯誤")InsertErr = NewError(3, "用戶注冊失敗")
)
2. 使用 httpx.Error 和 httpx.SetErrorHandler
接著修改user.go
文件:
/*....*/defer server.Stop()//httpx.SetErrorHandler 函數(shù)可以幫助你定義一個全局的錯誤處理邏輯,//該邏輯會在 HTTP handler 中捕獲到的所有錯誤中執(zhí)行。//它將允許你統(tǒng)一處理各類錯誤,返回更加一致和用戶友好的響應(yīng)。//httpx.SetErrorHandler 僅在調(diào)用了 httpx.Error 處理響應(yīng)時才有效。httpx.SetErrorHandler(func(err error) (int, any) {switch e := err.(type) {case *biz.Error:// 自定義一個 錯誤返回類型return http.StatusOK, biz.Fail(e)default:return http.StatusInternalServerError, nil}})ctx := svc.NewServiceContext(c)/*....*/
修改internal/handler/register/registerhandler.go
文件:
func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {var req types.RegisterRequestif err := httpx.Parse(r, &req); err != nil {//httpx.SetErrorHandler 僅在調(diào)用了 httpx.Error 處理響應(yīng)時才有效。//所以我們現(xiàn)在還是使用原來的httpx.ErrorCtxhttpx.ErrorCtx(r.Context(), w, err)return}l := register.NewRegisterLogic(r.Context(), svcCtx)resp, err := l.Register(&req)if err != nil {//httpx.SetErrorHandler 僅在調(diào)用了 httpx.Error 處理響應(yīng)時才有效。//所以我們現(xiàn)在還是使用原來的httpx.ErrorCtxhttpx.ErrorCtx(r.Context(), w, err)} else {//成功的請求,httpx.SetErrorHandler 是捕獲不到的// 所以需要我們自定義返回信息httpx.OkJsonCtx(r.Context(), w, biz.Success(resp))}}
}
3.實現(xiàn)統(tǒng)一的錯誤響應(yīng)機制
接下來,修改 internal/user/register/registerlogic.go
文件:
func (l *RegisterLogic) Register(req *types.RegisterRequest) (resp *types.RegisterResponse, err error) {// todo: add your logic here and delete this line/*...*/if user != nil {//return nil, errors.New(1, "用戶已注冊")return nil, biz.AlreadyRegister}//插入新的數(shù)據(jù)/*...*/if err != nil {//return nil, errors.New(2, "用戶注冊失敗")return nil, biz.InsertErr}}
接著運行測試