方式一、直接定义一个成功和失败的方法,在代码里面修改(对代码有侵入,每次都要修改代码)
-
1、封装一个统一返回的方法
gopackage utils import ( "github.com/zeromicro/go-zero/rest/httpx" "net/http" ) type Body struct { Code int `json:"code"` Message string `json:"message"` Result interface{} `json:"result,omitempty"` } func Response(w http.ResponseWriter, code int, message string, data interface{}) { httpx.OkJson(w, Body{ Code: code, Message: message, Result: data, }) } // Success 成功的请求 func Success(w http.ResponseWriter, data interface{}) { Response(w, 0, "请求成功", data) } // Fail 失败的请求 func Fail(w http.ResponseWriter, message string) { Response(w, 1, message, nil) }
-
2、修改代码的返回值方法调用
gofunc GetTestHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := demo.NewGetTestLogic(r.Context(), svcCtx) resp, err := l.GetTest() if err != nil { //httpx.ErrorCtx(r.Context(), w, err) utils.Fail(w, err.Error()) } else { //httpx.OkJsonCtx(r.Context(), w, resp) utils.Success(w, resp) } } }
方式二、在api
文件定义的时候直接返回的数据结构(在定义api
的时候繁琐了)
-
1、
api
文件中定义propertiestype Response { Code string `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } @server ( prefix: demo/v1 group: demo ) service demo-api { @doc "测试" @handler GetTest get /testApi returns (Response) }
-
2、在每次操作的时候可以写上
gofunc (l *GetTestLogic) GetTest() (resp *types.Response, err error) { return &types.Response{ Code: "0", Msg: "成功", Data: "hello world", }, nil }
-
3、参考官网地址
方式三、自定义模版,直接修改返回的数据方法(可以接受)
-
1、定义方法
gopackage utils import ( "encoding/json" "encoding/xml" "errors" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest/httpx" "net/http" ) type Body struct { Code int `json:"code"` Message string `json:"message"` Result interface{} `json:"result"` // omitempty json里面加了这个表示如果为空的时候字段不返回 } type PageVo struct { Data interface{} `json:"data"` // 数据 Total int64 `json:"total"` // 总条数 PageSize int64 `json:"pageSize"` // 当前条数 PageNumber int64 `json:"pageNumber"` // 当前页数 } // Response 一般返回 func Response(w http.ResponseWriter, resp interface{}, err error) { if err != nil { httpx.OkJson(w, Body{ Code: 1, Message: err.Error(), Result: nil, }) } else { httpx.OkJson(w, Body{ Code: 0, Message: "请求成功", Result: resp, }) } } // BuildPageData 返回分页数据 func BuildPageData(w http.ResponseWriter, resp interface{}, total, pageSize, pageNumber int64, err error) { if err != nil { httpx.OkJson(w, Body{ Code: 1, Message: err.Error(), Result: PageVo{ Data: nil, // 数据 Total: 0, // 总条数 PageSize: pageSize, // 当前条数 PageNumber: pageNumber, // 当前页数 }, }) } else { httpx.OkJson(w, Body{ Code: 0, Message: "请求成功", Result: PageVo{ Data: resp, // 数据 Total: total, // 总条数 PageSize: pageSize, // 当前条数 PageNumber: pageNumber, // 当前页数 }, }) } } func WriteString(w http.ResponseWriter, code int, v string) { w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.WriteHeader(code) if n, err := w.Write([]byte(v)); err != nil { // http.ErrHandlerTimeout has been handled by http.TimeoutHandler, // so it's ignored here. if !errors.Is(err, http.ErrHandlerTimeout) { logx.Errorf("write response failed, error: %s", err) } } else if n < len(v) { logx.Errorf("actual bytes: %d, written bytes: %d", len(v), n) } } func WriteXml(w http.ResponseWriter, code int, v interface{}) { bs, err := xml.Marshal(v) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/xml") w.Header().Set("response_body", string(bs)) w.WriteHeader(code) if n, err := w.Write(bs); err != nil { // http.ErrHandlerTimeout has been handled by http.TimeoutHandler, // so it's ignored here. if !errors.Is(err, http.ErrHandlerTimeout) { logx.Errorf("write response failed, error: %s", err) } } else if n < len(bs) { logx.Errorf("actual bytes: %d, written bytes: %d", len(bs), n) } } func WriteFile(w http.ResponseWriter, fileBytes []byte, err error) { var ( b []byte ) if err != nil { httpx.OkJson(w, err) b, _ = json.Marshal(err) w.Header().Set("response_body", string(b)) return } w.Header().Set("Content-Type", "application/octet-stream") if n, err := w.Write(fileBytes); err != nil { // http.ErrHandlerTimeout has been handled by http.TimeoutHandler, // so it's ignored here. if !errors.Is(err, http.ErrHandlerTimeout) { logx.Errorf("write response failed, error: %s", err) } } else if n < len(fileBytes) { logx.Errorf("actual bytes: %d, written bytes: %d", len(fileBytes), n) } w.WriteHeader(200) }
-
2、定义模版
handler.tpl
propertiespackage {{.PkgName}} import ( "net/http" "github.com/zeromicro/go-zero/rest/httpx" {{.ImportPackages}} ) func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { {{if .HasRequest}}var req types.{{.RequestType}} if err := httpx.Parse(r, &req); err != nil { utils.TranslatorError(w, r, err) return } {{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx) {{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}}) {{if .HasResp}}utils.Response(w, resp, err){{else}}utils.Response(w, nil, err){{end}} } }
-
3、使用自己的模版生成方法
propertiesgoctl api go -api *api --dir . --style=goZero --home ../../goctl
-
4、生成的代码中
gofunc DemoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.Request if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return } l := demo.NewDemoLogic(r.Context(), svcCtx) resp, err := l.Demo(&req) utils.Response(w, resp, err) } }
-
5、这种方式不好的地方,在每个项目中导包可能不一样的,需要手动改动模版,或者把封装的方法封装成一个库发布
方式四、使用拦截器(最优方案)
-
1、创建自己返回的方法
gopackage utils import ( "context" "github.com/zeromicro/go-zero/core/logx" "net/http" ) type Response struct { Code int64 `json:"code"` Message string `json:"message"` Result interface{} `json:"result,omitempty"` } func Success(data interface{}) *Response { return &Response{ Code: 0, Message: "请求成功", Result: data, } } func Fail(err string) *Response { return &Response{ Code: 1, Message: err, Result: nil, } } func OkHandler(_ context.Context, v interface{}) any { return Success(v) } func ErrHandler(name string) func(ctx context.Context, err error) (int, any) { return func(ctx context.Context, err error) (int, any) { // 日志记录 logx.WithContext(ctx).Errorf("【%s】 err %v", name, err) return http.StatusBadRequest, Fail(err.Error()) } }
-
2、在项目启动文件中添加自己的方法
go
// 使用拦截器
httpx.SetOkHandler(utils.OkHandler)
httpx.SetErrorHandlerCtx(utils.ErrHandler(c.Name))