关于go-zero单体服务使用泛型简化注册Handler路由的问题

当我们使用go-zero开发单体服务时,可能会遇到需要注册多个handler路由的情况,而这些handler的参数和返回值类型往往是类似的,这时就可以考虑使用泛型来简化注册过程。

具体步骤如下:

  1. 创建接口定义

首先,我们需要定义一个公共的接口,该接口包含了参数和返回值类型相同的方法定义,如下所示:

type CommonService interface {
    Ping(ctx context.Context, req *model.Request) (*model.Response, error)
}

该接口定义了一个名为Ping的方法,接收两个参数,分别是上下文和请求参数,返回两个值,即响应结果和错误。

  1. 实现接口方法

接下来,我们需要为要使用泛型注册的handler实现CommonService接口中的方法,代码示例如下:

type CommonServiceImpl struct {
    // 这里是服务实现的具体实现部分
}

func (s *CommonServiceImpl) Ping(ctx context.Context, req *model.Request) (*model.Response, error) {
    // 具体实现部分
}
  1. 注册handler路由

接下来,我们可以定义一个函数,使用go-zero的Go应用程序框架中的泛型函数NewHandler(T)来注册handler路由。这里的“T”就是我们定义的CommonService接口,这样就可以将实现该接口的handler路由动态注册进来。

具体代码示例如下:

func RegisterCommonServiceRoutes(engine *http.Server, svc CommonService) {
    registration.AddHandler(func(ctx *svccontext.ServiceContext) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            var (
                err     error
                req     *model.Request
                resp    *model.Response
                decoder = json.NewDecoder(r.Body)
            )

            if err = decoder.Decode(&req); err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
            }

            defer r.Body.Close()

            resp, err = svc.Ping(r.Context(), req)

            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(resp)
        })
    })
}

在上面的代码中,我们使用了go-zero提供的注册器registration.AddHandler()函数,将handler路由动态添加进去。注意,这里的参数ctx是ServiceContext类型的,而不是常规的context.Context类型,所以我们将它进行了转换。

  1. 启动应用程序

最后,我们需要从main函数中启动应用程序并注册handler路由。具体示例如下:

func main() {
    app := gozero.NewApp()
    engine := http.NewServer()

    svc := &CommonServiceImpl{}

    RegisterCommonServiceRoutes(engine, svc)

    app.Use(engine)

    app.Start()
}

在上面的代码中,我们定义了一个标准的go-zero应用程序,并将我们之前定义的engine加入到了app.Use()的中间件链中。最后启动app.Start()即可。

示例:

假设我们有两个handler路由,分别是HandleA和HandleB,它们的请求和响应参数类型都相同,我们就可以定义一个公共的接口CommonService来实现它们。

type CommonService interface {
    HandleA(ctx context.Context, req *model.Request) (*model.Response, error)
    HandleB(ctx context.Context, req *model.Request) (*model.Response, error)
}

接下来,我们为要使用泛型注册的handler实现CommonService接口中的方法:

type CommonServiceImpl struct {
    // 这里是具体实现部分
}

func (s *CommonServiceImpl) HandleA(ctx context.Context, req *model.Request) (*model.Response, error) {
    // 具体实现部分
}

func (s *CommonServiceImpl) HandleB(ctx context.Context, req *model.Request) (*model.Response, error) {
    // 具体实现部分
}

最后,我们可以注册handler路由:

func RegisterCommonServiceRoutes(engine *http.Server, svc CommonService) {
    registration.AddHandler(func(ctx *svccontext.ServiceContext) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            var (
                err     error
                req     *model.Request
                resp    *model.Response
                decoder = json.NewDecoder(r.Body)
            )

            if err = decoder.Decode(&req); err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
            }

            defer r.Body.Close()

            switch r.URL.Path {
            case "/handleA":
                resp, err = svc.HandleA(r.Context(), req)
            case "/handleB":
                resp, err = svc.HandleB(r.Context(), req)
            default:
                http.NotFound(w, r)
                return
            }

            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(resp)
        })
    })
}

在上面的示例代码中,我们注册了两个handler路由HandleA和HandleB,并使用switch语句来根据URL路径分发请求。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:关于go-zero单体服务使用泛型简化注册Handler路由的问题 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • 打造一款代码命名工具的详细教程

    下面是“打造一款代码命名工具的详细教程”的完整攻略。 1. 确定工具功能需求和实现方式 在打造一款代码命名工具之前,我们需要确定该工具的主要功能需求和实现方式。我们可以参考一些已有的命名工具,比如PascalCase、camelCase、kebab-case等等,根据自己的需求设计出适合自己的命名方式。 完成需求确定后,我们就需要开始考虑工具的具体实现方式。…

    GitHub 2023年5月16日
    00
  • 详解Vue项目引入CreateJS的方法(亲测可用)

    关于“详解Vue项目引入CreateJS的方法(亲测可用)”,下面是具体的攻略: 前置知识 在做这个项目之前,需要你了解以下技术: Vue.js CreateJS Webpack 步骤一:安装CreateJS 使用npm安装CreateJS: npm install createjs –save 或者使用yarn安装CreateJS: yarn add c…

    GitHub 2023年5月16日
    00
  • 从0快速搭建一个实用的MVVM框架(超详细)

    “从0快速搭建一个实用的MVVM框架(超详细)”是一篇关于搭建MVVM框架的教程,其中包括了两个示例进行说明。以下是该攻略的详细讲解: 1. 准备工作 在这一部分,作者对搭建MVVM框架的准备工作进行了介绍,包括了准备开发环境、设计框架结构等。其中,作者提到要使用Vue.js和Webpack,需要配置相应的环境和插件。 2. 实现一个简单的Todo应用 在这…

    GitHub 2023年5月16日
    00
  • Win10 20H1快速预览版18990今日推送 更新内容汇总

    Win10 20H1快速预览版18990更新内容汇总 Windows10系统不断更新,新的20H1版本也在紧锣密鼓的开发中,微软已经发布了Win10 20H1快速预览版18990更新,以下是该更新的内容汇总。 更新内容 1. 设置应用增加了控制中心选项 在设置应用程序中,增加了控制中心选项。在“设备”下拉菜单中,用户可以找到“控制中心”选项。点击进入后,可以…

    GitHub 2023年5月16日
    00
  • Go easyjson使用及反射原理

    Go easyjson是一个用于快速序列化和反序列化JSON数据的库,它比标准库中的encoding/json更快,并且支持代码生成以减少运行时的开销。下面是使用easyjson和反射的详细攻略,包含两个示例: 1. 使用easyjson 安装 要使用easyjson,需要安装它的生成器: $ go get github.com/mailru/easyjso…

    GitHub 2023年5月16日
    00
  • 在vscode中使用Git的教程

    使用Git管理代码是现代软件开发的标配之一。在Visual Studio Code (VS Code)中使用Git能够方便地进行代码管理、版本控制、协同开发等操作。接下来,我们将为你详细介绍如何在VS Code中使用Git。 一、安装Git 在使用Git前,首先需要在本地安装Git。你可以前往Git官网(https://git-scm.com/)下载对应系统…

    GitHub 2023年5月16日
    00
  • Android巧用Fragment解耦onActivityResult详解

    下面我将详细讲解“Android巧用Fragment解耦onActivityResult详解”攻略,并附上两条示例说明。 概述 在 Android 开发中,遇到需要调用其他 Activity 并返回结果的情况时,常常使用 startActivityForResult() 方法。但是,onActivityResult() 方法所处理的逻辑通常较为复杂,且需在 …

    GitHub 2023年5月16日
    00
  • Android实现网易云音乐的旋转专辑View

    以下是Android实现网易云音乐的旋转专辑View的完整攻略: 说明 在实现旋转专辑View之前,我们首先需要掌握以下知识: View的绘制 动画 Matrix变换 示例一:自定义View实现旋转效果 首先,我们需要创建一个自定义View,这个View将用于显示旋转的专辑图片。 public class AlbumView extends ImageVie…

    GitHub 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部