go-zero统一Response的返回值(RPC端错误没有解析到)
统一Response的返回值
说明
最完整版本推荐使用当前项目方式,支持捕捉RPC端,官方后续好像会支持这种错误模式(作者提过)
github.com/Mikaelemmmm/go-zero-loo...
官方参考资料
参考1:官网的【模板管理】=》【自定义模板】
参考2:官网的【项目开发】=》【业务开发】=》【错误处理】
go-zero.dev/cn/error-handle.html
步骤一:新创建自己的错误处理相关函数
【说明】:你拿去使用,需要将”go-slot/utils/errorx”等import路径改成你自己实际的路径。我当前项目名称叫go-slot,utils是我的一个工具包。
1.官方给的代码:
package response
import (
"net/http"
"github.com/tal-tech/go-zero/rest/httpx"
)
type Body struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
func Response(w http.ResponseWriter, resp interface{}, err error) {
var body Body
if err != nil {
body.Code = -1
body.Msg = err.Error()
} else {
body.Msg = "OK"
body.Data = resp
}
httpx.OkJson(w, body)
}
- 我此时修改的代码目录如下,代码拿去,需要你自己修改相关的import信息,小呆瓜别直接用
//baseerror.go和response.go的路径
utils
├─ common.go
├─ errorx
│ └─ baseerror.go
├─ http_rpc.go
├─ md5.go
└─ response
└─ response.go
2.1. utils/response/response.go代码如下:
//utils/response/response.go代码
package response
import (
"github.com/tal-tech/go-zero/rest/httpx"
"go-slot/utils/errorx"
"net/http"
)
type Body struct {
Code int `json:"code"`
Message string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
//统一封装成功响应值
func Response(w http.ResponseWriter, resp interface{}, err error) {
var body Body
if err != nil {
switch e := err.(type) {
case *errorx.CodeError://业务输出错误
body.Code = e.Code
body.Message = e.Message
body.Data = e.Data
//body.Data = e.Data()
default: //系统未知错误
body.Code = 1
body.Message = err.Error()
}
} else {
body.Code = 0
body.Message = "请求成功!"
body.Data = resp
}
httpx.OkJson(w, body)
}
2.2. utils/errorx/baseerror.go代码如下:
package errorx
//定义错误类型
const defaultCode = 1001
type CodeError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
func NewCodeError(code int, msg string) error {
return &CodeError{Code: code, Message: msg}
}
func NewErrorData(code int, msg string,data interface{}) error {
return &CodeError{Code: code, Message: msg, Data: data}
}
func NewDefaultError(msg string) error {
return NewCodeError(defaultCode, msg)
}
func (e *CodeError) Error() string {
return e.Message
}
//------------------Response响应值----------------------
//func (e *CodeError) Info()响应返回值
type CodeErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
//返回相关参数
func (e *CodeError) Info() *CodeErrorResponse {
return &CodeErrorResponse{
Code: e.Code,
Message: e.Message,
Data: e.Data,
}
}
步骤二:生成本地goctl缓存模板
1.随机开启一个CMD窗口使用模板初始化命令goctl template init
进行初始化,如果本地没有~/.goctl/api/handler.tpl
文件 的话。
mac环境对应的路径就是~/.goctl/api。
window路径会是C:\Users\【你的电脑用户名】.goctl,此时我的模板路径是C:\Users\DELL.goctl\1.2.3-cli\api,其中DELL是此时的用户名。
goctl完整模板结构如下:
.goctl
└─ 1.2.3-cli
├─ api
│ ├─ config.tpl
│ ├─ context.tpl
│ ├─ etc.tpl
│ ├─ handler.tpl
│ ├─ handler官方模板.tpl
│ ├─ logic.tpl
│ ├─ main.tpl
│ └─ template.tpl
├─ docker
│ └─ docker.tpl
├─ kube
│ ├─ deployment.tpl
│ └─ job.tpl
├─ model
│ ├─ delete.tpl
│ ├─ err.tpl
│ ├─ field.tpl
│ ├─ find-one-by-field-extra-method.tpl
│ ├─ find-one-by-field.tpl
│ ├─ find-one.tpl
│ ├─ import-no-cache.tpl
│ ├─ import.tpl
│ ├─ insert.tpl
│ ├─ interface-delete.tpl
│ ├─ interface-find-one-by-field.tpl
│ ├─ interface-find-one.tpl
│ ├─ interface-insert.tpl
│ ├─ interface-update.tpl
│ ├─ model-new.tpl
│ ├─ model.tpl
│ ├─ tag.tpl
│ ├─ types.tpl
│ ├─ update.tpl
│ └─ var.tpl
├─ mongo
│ ├─ err.tpl
│ └─ model.tpl
├─ newapi
│ └─ newtemplate.tpl
└─ rpc
├─ call-func.tpl
├─ call-interface-func.tpl
├─ call.tpl
├─ config.tpl
├─ etc.tpl
├─ logic-func.tpl
├─ logic.tpl
├─ main.tpl
├─ server-func.tpl
├─ server.tpl
├─ svc.tpl
└─ template.tpl
步骤三:修改goctl的handel模板
【说明】:你拿去使用需要修改import
3.1. 官方默认的handel模板
package {{.PkgName}}
import (
"net/http"
{{if .After1_1_10}}"github.com/tal-tech/go-zero/rest/httpx"{{end}}
{{.ImportPackages}}
)
func {{.HandlerName}}(ctx *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 {
httpx.Error(w, err)
return
}
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), ctx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}req{{end}})
if err != nil {
httpx.Error(w, err)
} else {
{{if .HasResp}}httpx.OkJson(w, resp){{else}}httpx.Ok(w){{end}}
}
}
}
3.2. 我修改之后的handel模板完整代码
package {{.PkgName}}
import (
"go-slot/utils/response"
"net/http"
{{if .After1_1_10}}"github.com/tal-tech/go-zero/rest/httpx"{{end}}
{{.ImportPackages}}
)
func {{.HandlerName}}(ctx *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 {
httpx.Error(w, err)
return
}
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), ctx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}req{{end}})
{{if .HasResp}}response.Response(w, resp, err){{else}}response.Response(w, nil, err){{end}}
}
}
其实就是做了2件事情。
第1件事:删除官方模板的如下代码
if err != nil {
httpx.Error(w, err)
} else {
{{if .HasResp}}httpx.OkJson(w, resp){{else}}httpx.Ok(w){{end}}
}
第2件事:新增如下代码,其中
{{if .HasResp}}response.Response(w, resp, err){{else}}response.Response(w, nil, err){{end}}
//注意导入你自己response.Response对应的import
步骤四:去任意一个logic的方法验证结果
//记得import自己对应的路径
err := errorx.NewDefaultError("添加会员地址失败") //默认code错误
err := errorx.NewErrorData(400,"错误","数据错误") //指定任意错误data信息
err := errorx.NewCodeError(400,"错误") //指定code和message信息
本作品采用《CC 协议》,转载必须注明作者和本文链接