如何高效开发基于gin的http服务

前言

在使用go开发http服务的时候,我们会频繁的定义请求和返回结构体,还有路由,很浪费时间。那有没有一种方法可以让我们避免这种频繁或者减少频率呢。protoc-gen-hip帮助我们解决了这个问题。基于protobuffer去生成自动生成我们需要的api代码逻辑

protoc-gen-hip

如何使用

下载工具

  1. 下载protoc

首先需要下载protoc mac系统:brew install protoc

其他系统:github.com/protocolbuf…

  1. 下载protoc-gen-hip

// go 1.17以前

go get -u github.com/GodWY/protoc-gen-hip@latest go install github.com/GodWY/protoc-gen-hip

// go1.17后

go install github.com/GodWY/protoc-gen-hip@latest

定义protobuffer

定义请求

syntax="proto3";
package account;

option go_package="pkg/gen/http/account";


message SendSmsCodeRQ {
   // @gotags: json:"phone_num"
   string PhoneNum = 1;
}

message SendSmsCodeRS {
}

定义http服务


//@import:xxx.xxx.xxx @import:xxx.xxxx.xxxx
//@middle:xxx.Has()
//@root:/api/xx
service Account{
   //@method:POST @middle:xxx.Has()
   rpc SendSmsCode(SendSmsCodeRQ) returns (SendSmsCodeRS);
}

执行代码生成

protoc - --proto_path=. --hip_out=./ --go_out=./ ./proto/*.proto

生成的代码

    // Code generated by protoc-gen-go-hip. DO NOT EDIT.
// versions:v1.2.0

package account

// This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against.
import (
   "net/http"
   "github.com/GodWY/gutil"
   "xxx.xxx.xxx"

   "github.com/gin-gonic/gin"
)

// generated http method
func registerAccountHttpHandler(srv *gin.Engine, srvs AccountHttpHandler) {
   group := srv.Group("/api/account", xxx.Has())
   group.POST("/v1/sendSmsCode", srvs.SendSmsCode, xxx.Has())
   group.POST("/v1/accessLogin", srvs.AccessLogin)
}

var TAccount Account

func RegisterAccountHttpHandler(srv *gin.Engine, srvs Account) {
   tmp := new(xxx_Account)
   registerAccountHttpHandler(srv, tmp)
   TAccount = srvs
}

type Account interface {
   SendSmsCode(ctx *gin.Context, in *SendSmsCodeRQ) (out *SendSmsCodeRS, err error)
   AccessLogin(ctx *gin.Context, in *AccessLoginRQ) (out *AccessLoginRS, err error)
}

// generated http handle
type AccountHttpHandler interface {
   SendSmsCode(ctx *gin.Context)
   AccessLogin(ctx *gin.Context)
}

type xxx_Account struct {
}

func (xx *xxx_Account) SendSmsCode(ctx *gin.Context) {
   req := &SendSmsCodeRQ{}
   if ok := ctx.Bind(req); ok != nil {
      detail := "bind request error"
      rt := gutil.RetFail(10000, detail)
      ctx.JSON(http.StatusOK, rt)
      return
   }
   rsp, err := TAccount.SendSmsCode(ctx, req)

   if err != nil {
      ctx.JSON(http.StatusOK, gutil.RetError(err))
      return
   }
   ctx.JSON(http.StatusOK, gutil.RetSuccess("success", rsp))
}

func (xx *xxx_Account) AccessLogin(ctx *gin.Context) {
   req := &AccessLoginRQ{}
   if ok := ctx.Bind(req); ok != nil {
      detail := "bind request error"
      rt := gutil.RetFail(10000, detail)
      ctx.JSON(http.StatusOK, rt)
      return
   }
   rsp, err := TAccount.AccessLogin(ctx, req)

   if err != nil {
      ctx.JSON(http.StatusOK, gutil.RetError(err))
      return
   }
   ctx.JSON(http.StatusOK, gutil.RetSuccess("success", rsp))
}

注释说明


5. 支持导入三方包,自定义中间件和自定义路由

> 所有的自定义代码都是通过注释读取的。

- 自定义组中间件
> 每一个service对应gin都是一个组,定义组路由只需要使用`@middle:`关键字即可,value是对应的方法
- 导入项目包
> 在service中定义 `@import` 可以连续定义多个导入包

- 定义接口请求

> 在每个rpc接口中,自定义请求方法 `@method` 即可目前支持GET,POST,ANY 不区分大小写

- 定义接口中间件
> 在接口注释中 `@middle` 即可定义自定义和gin中间件

- 如何自定义组路由

> 在service 定义`@root`即可

使用

    ```
package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
)

type AccSrc struct {
   
}

func (a AccSrc) SendSmsCode(ctx *gin.Context, in *account.SendSmsCodeRQ) (out *account.SendSmsCodeRS, err error) {
   panic("implement me")
}

func (a AccSrc) AccessLogin(ctx *gin.Context, in *account.AccessLoginRQ) (out *account.AccessLoginRS, err error) {
   panic("implement me")
}

func main() {
   en := gin.New()
   ac:=&AccSrc{}
   account.RegisterAccountHttpHandler(en,ac)

   en.Run(":8081")
}

func Logger() gin.HandlerFunc {
   return func(context *gin.Context) {
      fmt.Printf("xxxxxx1")
   }
}

总结

我们利用pb来实现路由的生成可以帮助我们快速的生成http代码

猜你喜欢

转载自juejin.im/post/7120539830676619294
今日推荐