当前位置: 首页 > news >正文

Go-zero框架修改模版进行handler统一响应封装

使用go-zero快速生成接口的时候,发现还是有一些情况不太好处理,比如说,想要自定义响应封装等等。

最开始第一版写api文件的时候,写法是这样的。

type LoginRequest {UserName string `json:"userName"`Password string `json:"password"`
}type Response {Code int    `json:"code"`Data string `json:"data"`Msg  string `json:"msg"`
}type UserInfo {UserName string `json:"userName"`Addr     string `json:"addr"`Id       uint   `json:"id"`
}type UserInfoResponse {Code int      `json:"code"`Data UserInfo `json:"data"`Msg  string   `json:"msg"`
}service users {@handler loginpost /api/users/login (LoginRequest) returns (Response)@handler userInfoget /api/users/info returns (UserInfoResponse)
}// goctl api go -api v1.api -dir .

后面发现可以不把code、data、msg这三个重要信息写在api里边,而是通过统一封装,在统一响应中去加上code、data、msg,使之成为我们一个公共的库供我们使用。

首先我们封装好response文件:

package responseimport ("github.com/zeromicro/go-zero/rest/httpx""net/http"
)type Body struct {Code uint32      `json:"code"`Msg  string      `json:"msg"`Data interface{} `json:"data"`
}// Response http返回
func Response(r *http.Request, w http.ResponseWriter, resp interface{}, err error) {if err == nil {//成功返回r := &Body{Code: 0,Msg:  "成功",Data: resp,}httpx.WriteJson(w, http.StatusOK, r)return}//错误返回errCode := uint32(7)// 可以根据错误码,返回具体错误信息//errMsg := "服务器错误"httpx.WriteJson(w, http.StatusOK, &Body{Code: errCode,Msg:  err.Error(),Data: nil,})}

此时还需要考虑问题,假设我们只是需要这个项目使用统一的封装,不希望后面的go-zero项目受到影响,那么我们可以通过直接在本地生成模版文件去给当前这个项目使用。

然后我看了go-zero的官方文档,发现确实可以这么操作,ok,尝试一波。

首先,通过在本地(项目路径下)生成模版文件:

goctl template init --home template

在这里插入图片描述
然后可以看到提示成功了,并且生成了下面的模版。

在这里插入图片描述
下面是原api中的hanlder.tpl文件的代码:

package {{.PkgName}}import ("net/http""github.com/zeromicro/go-zero/rest/httpx"{{.ImportPackages}}
){{if .HasDoc}}{{.Doc}}{{end}}
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 {httpx.ErrorCtx(r.Context(), w, err)return}{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx){{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})if err != nil {httpx.ErrorCtx(r.Context(), w, err)} else {{{if .HasResp}}httpx.OkJsonCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}}}
}

修改后的tpl文件如下:

package handlerimport ("net/http""fim/common/response"{{.ImportPackages}}{{if .HasRequest}}"github.com/zeromicro/go-zero/rest/httpx"{{end}}
)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 {response.Response(r, w, nil, err)return}{{end}}l := logic.New{{.LogicType}}(r.Context(), svcCtx){{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}}){{if .HasResp}}response.Response(r, w, resp, err){{else}}response.Response(w, nil, err){{end}}}
}

简单来分析下这个代码逻辑,就是使用了模板引擎的语法(如 {{.HandlerName}}{{if .HasRequest}}),这些模板变量和条件判断在代码生成时会被具体的值替换。

首先,“fim/common/response”:项目中自定义的模块,提供了统一的响应处理方法。

然后是:{{.ImportPackages}}:模板变量,表示在代码生成时会根据需要动态导入其他必要的包。

    {{.ImportPackages}}{{if .HasRequest}}"github.com/zeromicro/go-zero/rest/httpx"{{end}}

func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc{{.HandlerName}} 是模板变量,表示具体的处理函数名称。例如,它可能会被替换为 LoginHandler

svcCtx *svc.ServiceContext:服务上下文,包含了依赖注入的配置和数据库连接等信息。然后返回handlerFunc


如果当前接口需要解析请求体({{if .HasRequest}}),则会执行以下操作:定义一个变量 req,类型为 types.{{.RequestType}}{{.RequestType}} 是模板变量,表示请求体的类型,例如 LoginRequest

{{if .HasRequest}}var req types.{{.RequestType}}if err := httpx.Parse(r, &req); err != nil {response.Response(r, w, nil, err)return}{{end}}

使用 httpx.Parse(r, &req) 解析 HTTP 请求体到 req 中。如果解析失败(err != nil),调用 response.Response 方法返回错误响应,并结束处理。


然后是进行逻辑处理:创建一个业务逻辑对象 l,类型为 logic.New{{.LogicType}}{{.LogicType}} 是模板变量,表示具体的业务逻辑类型,例如 LoginLogic。

调用业务逻辑对象的 {{.Call}} 方法({{.Call}} 是模板变量,表示具体的业务逻辑方法名,例如 Login)。

       l := logic.New{{.LogicType}}(r.Context(), svcCtx){{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}}){{if .HasResp}}response.Response(r, w, resp, err){{else}}response.Response(w, nil, err){{end}}

如果接口有返回值({{if .HasResp}}),则将返回值存储到 resp 中;否则,仅处理错误。

如果接口有返回值({{if .HasResp}}),调用 response.Response(r, w, resp, err),将业务逻辑的返回值作为响应数据返回。

如果接口没有返回值,仅调用 response.Response(w, nil, err),返回错误信息或成功状态。


然后把原来的api生成的handler和logic删除,然后重新生成一下。注意选对好对应目录下的template(这里我是在auth_api路径下去运行这个命令,也就是跟api文件同级目录下去运行)。

goctl api go -api auth_api.api -dir . --home ../../template

在这里插入图片描述
运行成功,看看效果。

在这里插入图片描述
这个时候发现生成的接口函数那些就没问题了。

在这里插入图片描述

http://www.xdnf.cn/news/31609.html

相关文章:

  • 手撕 简易HashMap
  • YOLO11改进-Backbone-使用MobileMamba替换YOLO backbone 提高检测精度
  • 在服务器上部署MinIO Server
  • JMeter实现UI自动化测试的完整方案
  • 配置管理与系统文档
  • MyImgConverter:图片批量处理工具
  • 智能提示语全周期优化系统:云原生架构设计与工程实践
  • LPDDR中读操作不存在Additive Latency(AL)的技术思考
  • opencv 最近邻插值法的原理
  • 集合框架(详解)
  • 手机投屏到电视方法
  • 从UDS协议学习ISO网络七层架构:汽车诊断网络协议的分层逻辑剖析
  • vue3专题1------父组件中更改子组件的属性
  • 应急响应篇近源攻击Docker镜像容器分析Dockfile路径定位基线扫描
  • MPTCP 的吞吐困局
  • 数据库基础-B+树
  • 使用 #pragma warning(push) 局部开启更高等级
  • 性能比拼: Elixir vs Go
  • MATLAB 控制系统设计与仿真 - 39
  • 春和景明-C语言简单代码
  • 又一张支付牌照注销
  • 实现窗口函数
  • Python+Selenium+Pytest+POM自动化测试框架封装(完整版)
  • M|触碰你
  • HTML+CSS+JS(1)
  • 深度学习数据预处理:Dataset类的全面解析与实战指南
  • 基于机器学习 LSTM 算法的豆瓣评论情感分析系统
  • 方法引用和构造器引用
  • vulnhub靶场之【hacker-kid】靶机
  • 洛谷 P2606 [ZJOI2010] 排列计数