实现gin框架增强(ginplus)支持openAPI文档

306 阅读3分钟

ginplus地址

前文链接 实现gin框架增强(ginplus)

gin plus

用于对gin框架增强, 实现根据结构体+结构体方法名实现路由注册、文档生成等功能

安装

go mod init "your-pkg-name"
go get -u github.com/aide-cloud/gin-plus
  • 目录结构
.
├── cmd.go
├── go.mod
└── go.sum

我们来看看实际生产中如何使用它, 下面会以一个简单的增删改查API 进行举例说明

package main

import (
    "context"
    "log"

    ginplush "github.com/aide-cloud/gin-plus"

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

// 定义所需的结构体
type (
    // 路由controller结构体, 它用于完成业务逻辑方法实现和路由注入, 对内部属性无要求
    Api struct {
    }

    // API详情请求参数, 意思是通过id获取API详情
    ApiDetailReq struct {
       Id uint `uri:"id"` // uri是表示从url路径中获取参数, 例如我们的url格式是/api/:id, 实际使用过程中调用的api就是/api/123这种, 那么id获取的值就是123
    }

    // API详情返响应参数
    ApiDetailResp struct {
       Id     uint   `json:"id"`     // 通过请求参数中id从存储中取到相同ID的数据
       Name   string `json:"name"`   // API名称, 用于模拟实际业务
       Remark string `json:"remark"` // API备注
    }

    // API列表查询请求参数
    ApiListReq struct {
       Current   int    `form:"current"`  // 请求的页码(用于分页查询)
       Size      int    `form:"size"`     // 请求的数据量(用于分页)
       Keryworld string `form:"keyworld"` // 关键字, 一般用于模糊查询
    }
    // API列表响应参数
    ApiListResp struct {
       Total   int64          `json:"total"`   // 满足条件的数据总数
       Current int            `json:"current"` // 对应请求当中的分页页码
       Size    int            `json:"size"`    // 对应请求当中的分页条数
       List    []*ApiInfoItem `json:"list"`    // 实际的数据列表
    }

    // API数据详情, 字段解释同上
    ApiInfoItem struct {
       Name   string `json:"name"`
       Id     uint   `json:"id"`
       Remark string `json:"remark"`
    }

    // API修改请求参数
    ApiUpdateReq struct {
       Id     uint   `uri:"id"`     // 根据ID修改, 来源url参数
       Name   string `json:"name"`  // 要修改的新名
       Remark string `json:"remark"`// 要修改的新备注
    }
    // API修改响应参数
    ApiUpdateResp struct {
       Id uint `json:"id"` // 请求成功返回被修改的数据ID
    }
    
    // API删除请求参数
    DelApiReq struct {
       Id uint `uri:"id"`  // 根据ID查询满足条件的数据执行删除
    }

    // API删除响应参数
    DelApiResp struct {
       Id uint `json:"id"` // 返回请求成功呗删除掉数据ID
    }
)

// GetDetail 查询API详情的接口, 生成后路由对应 GET /api/detail/:id
func (l *Api) GetDetail(ctx context.Context, req *ApiDetailReq) (*ApiDetailResp, error) {
    log.Println("Api.GetDetail")
    return &ApiDetailResp{
       Id:     req.Id,
       Name:   "demo",
       Remark: "hello world",
    }, nil
}

// GetList 查询API列表的接口, 生成后路由对应 GET /api/list
func (l *Api) GetList(ctx context.Context, req *ApiListReq) (*ApiListResp, error) {
    log.Println("Api.GetList", req)
    return &ApiListResp{
       Total:   100,
       Current: req.Current,
       Size:    req.Size,
       List: []*ApiInfoItem{
          {
             Id:     10,
             Name:   "demo",
             Remark: "hello world",
          },
       },
    }, nil
}

// UpdateInfo 修改API的接口, 生成后路由对应 Put /api/info:id
func (l *Api) PutInfo(ctx context.Context, req *ApiUpdateReq) (*ApiUpdateResp, error) {
    log.Println("Api.UpdateInfo")
    return &ApiUpdateResp{Id: req.Id}, nil
}

// DeleteInfo 删除API的接口, 生成后的路由对应 DELETE /api/info/:id
func (l *Api) DeleteInfo(ctx context.Context, req *DelApiReq) (*DelApiResp, error) {
    log.Println("Api.DeleteInfo")
    return &DelApiResp{Id: req.Id}, nil
}

func main() {
    // 初始化一个gin实例
    r := gin.Default()
    opts := []ginplush.Option{
       // 路由controller, 会根据该controller的方法名注册路由
       ginplush.WithControllers(&Api{}),
    }
    // 初始化一个ginplus实例
    ginInstance := ginplush.New(r, opts...)
    // 在8080端口上启动服务
    ginInstance.Run(":8080")
}
  • 生成的路由

image.png

  • 生成的文档地址

image.png

  • 文档查看

image.png

  • 运行项目后生成后的新增openapi.yaml, 如果已经生成过会更新该文件
.
├── cmd.go
├── go.mod
├── go.sum
└── openapi.yaml