Skip to main content Link Menu Expand (external link) Document Search Copy Copied

5、goRESTApiGen

goRESTApiGen是什么?

goRESTApiGen 是一个用go语言写的 RESTFUL API 生成工具,支持生成控制器、service层和model层,包括swagger注释,目前只支持mongodb

安装

go install github.com/imoowi/goRESTApiGen@latest

使用

切换到项目根目录下,执行以下操作

goRESTApiGen -a appname

例如我要生成对商品(goods)的api

$ goRESTApiGen -a goods
module=goRESTApiGen-goods
appname= goods
path= goods
service= goods
model= goods
modelpath makedir success.
modelFile path =  ./models/goods.model.go
file[models/GoodsModel.model.go] generated!
servicepath makedir success.
modelFile path =  ./services/goods.service.go
file[services/GoodsService.service.go] generated!
apppath makedir success.
modelFile path =  ./app/goods/goods.handler.go
file[app/goods/goods.handler.go] generated!
modelFile path =  ./app/goods/router.go
file[app/goods/router.go] generated!

会生成以下文件

$ tree
.
|-- app
|   `-- goods
|       |-- goods.handler.go
|       `-- router.go
|-- go.mod
|-- models
|   `-- goods.model.go
`-- services
    `-- goods.service.go

4 directories, 5 files
  • app/goods/goods.handler.go

package goods
import (
	"net/http"
	"github.com/gin-gonic/gin"
	"goRESTApiGen-goods/models"
	"goRESTApiGen-goods/services"
	"github.com/imoowi/goRESTApiGen/util/response"
	"github.com/spf13/cast"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

var goodsService *services.GoodsService
	

//	@Summary	列表
//	@Tags		goods
//	@Accept		application/json
//	@Produce	application/json
//	@Param		Authorization	header		string					true	"Bearer 用户令牌"
//	@Param		page			query		int						true	"页码 (1)"
//	@Param		pageSize		query		int						false	"页数"
//	@Success	200				{object}	response.ResponseList	"成功"
//	@Failure	400				{object}	string					"请求错误"
//	@Failure	401				{object}	string					"token验证失败"
//	@Failure	500				{object}	string					"内部错误"
//	@Router		/api/goods [get]
func List(c *gin.Context) {
	searchKey := c.DefaultQuery("searchKey", "")
	page := cast.ToInt64(c.DefaultQuery("page", "1"))
	pageSize := cast.ToInt64(c.DefaultQuery("pageSize", "20"))
	pages, list := goodsService.List(searchKey, page, pageSize)
	res := gin.H{
		"pages": pages,
		"list":  list,
	}
	response.OK(res, c)
}



//	@Summary	添加
//	@Tags		goods
//	@Accept		application/json
//	@Produce	application/json
//	@Param		Authorization	header		string					true	"Bearer 用户令牌"
//	@Param		body			body		models.GoodsModel	true	"models.GoodsModel"
//	@Success	200				{object}	string					"成功"
//	@Failure	400				{object}	string					"请求错误"
//	@Failure	401				{object}	string					"token验证失败"
//	@Failure	500				{object}	string					"内部错误"
//	@Router		/api/goods [post]
func Add(c *gin.Context) {
	var goodsModel *models.GoodsModel
	err := c.ShouldBindJSON(&goodsModel)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	id, err := goodsService.Add(goodsModel)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	response.OK(id, c)
}


//	@Summary	修改
//	@Tags		goods
//	@Accept		application/json
//	@Produce	application/json
//	@Param		Authorization	header		string					true	"Bearer 用户令牌"
//	@Param		id				query		string					true	"id"
//	@Param		body			body		models.GoodsModel	true	"models.GoodsModel"
//	@Success	200				{object}	string					"成功"
//	@Failure	400				{object}	string					"请求错误"
//	@Failure	401				{object}	string					"token验证失败"
//	@Failure	500				{object}	string					"内部错误"
//	@Router		/api/goods/:id [put]
func Update(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		response.Error("pls input id", http.StatusBadRequest, c)
		return
	}
	var goodsModel *models.GoodsModel
	err := c.ShouldBindJSON(&goodsModel)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	goodsModel.Id, err = primitive.ObjectIDFromHex(id)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	updated, err := goodsService.Update(goodsModel)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	response.OK(updated, c)
}


//	@Summary	删除
//	@Tags		goods
//	@Accept		application/json
//	@Produce	application/json
//	@Param		Authorization	header		string					true	"Bearer 用户令牌"
//	@Param		id				query		string					true	"id"
//	@Success	200				{object}	string					"成功"
//	@Failure	400				{object}	string					"请求错误"
//	@Failure	401				{object}	string					"token验证失败"
//	@Failure	500				{object}	string					"内部错误"
//	@Router		/api/goods/:id [delete]
func Delete(c *gin.Context) {
	id := c.Param("id")
	if id == " "{
		response.Error("pls input id", http.StatusBadRequest, c)
		return
	}
	deleted, err := goodsService.Delete(id)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	response.OK(deleted, c)
}

//	@Summary	单个信息
//	@Tags		goods
//	@Accept		application/json
//	@Produce	application/json
//	@Param		Authorization	header		string					true	"Bearer 用户令牌"
//	@Param		id				query		string					true	"id"
//	@Success	200				{object}	string					"成功"
//	@Failure	400				{object}	string					"请求错误"
//	@Failure	401				{object}	string					"token验证失败"
//	@Failure	500				{object}	string					"内部错误"
//	@Router		/api/goods/:id [get]
func GetOne(c *gin.Context) {
	id := c.Param("id")
	if id == " "{
		response.Error("pls input id", http.StatusBadRequest, c)
		return
	}
	info, err := goodsService.GetOne(id)
	if err != nil {
		response.Error(err.Error(), http.StatusBadRequest, c)
		return
	}
	response.OK(info, c)
}

  • app/goods/router.go

package goods
import (
	"goRESTApiGen-goods/middleware"
	"goRESTApiGen-goods/router"

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

func init() {
	router.RegisterRoute(Routers)
}


func Routers(e *gin.Engine) {

	e.Use(middleware.RuntimeMiddleware())
	_goods := e.Group("/api/goods")
	{
		//验证登录
		_goods.Use(middleware.JWTAuthMiddleware())
		//验证权限
		_goods.Use(middleware.CasbinMiddleware())

		_goods.GET("", List)
		_goods.POST("", Add)
		_goods.PUT("/:id", Update)
		_goods.DELETE("/:id", Delete)
		_goods.GET("/:id", GetOne)
	}
}


  • models/goods.model.go

package models

import (
	"context"
	"log"
	"time"
	"goRESTApiGen-goods/global"
	"github.com/imoowi/goRESTApiGen/util/response"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
)
const TABLE_NAME_GOODS = "goods"

type GoodsModel struct {
	Id        primitive.ObjectID `json:"id" bson:"_id,omitempty"`
	Name      string             `json:"name" bson:"name" binding:"required"`
	CreatedAt int64              `json:"createdAt" bson:"createdAt"`
	Deleted   bool               `json:"-" bson:"deleted"`
	// add your code below

}
	
// 列表
func (m *GoodsModel) List(searchKey string, page int64, pageSize int64) (pages response.Pages, res []*GoodsModel) {
	coll := global.Mongo.Collection(TABLE_NAME_GOODS)
	filter := bson.M{}
	filter["deleted"] = false
	if searchKey != "" {
		filter["name"] = bson.M{"$regex": primitive.Regex{Pattern: searchKey, Options: "i"}}
	}

	count, err := coll.CountDocuments(context.TODO(), filter)
	if err != nil {
		log.Fatal(err)
	}
	cur, err := coll.Find(context.TODO(),
			filter,
			options.Find().SetLimit(pageSize),
			options.Find().SetSkip(pageSize*(page-1)),
			options.Find().SetSort(bson.M{
				"createdAt": -1,
			}),
	)
	if err != nil {
		log.Fatal(err)
	}
	cur.All(context.TODO(), &res)
	if err := cur.Err(); err != nil {
		log.Fatal(err)
	}
	cur.Close(context.TODO())
	pages = response.MakePages(count, page, pageSize)
	return
}	

// 添加
func (m *GoodsModel) Add(goodsModel *GoodsModel) (newId string, err error) {
	goodsModel.CreatedAt = time.Now().Unix()
	coll := global.Mongo.Collection(TABLE_NAME_GOODS)
	res, err := coll.InsertOne(context.TODO(), goodsModel)
	insertedId := res.InsertedID
	newId = insertedId.(primitive.ObjectID).Hex()
	return
}


// 修改
func (m *GoodsModel) Update(goodsModel *GoodsModel) (updated bool, err error) {
	coll := global.Mongo.Collection(TABLE_NAME_GOODS)
	_id, _ := primitive.ObjectIDFromHex(goodsModel.Id.Hex())
	wareByte, _ := bson.Marshal(goodsModel)
	updateFields := bson.M{}
	bson.Unmarshal(wareByte, &updateFields)
	update := bson.M{
		"$set": updateFields,
	}
	res, err := coll.UpdateByID(context.TODO(), _id, update)
	return res.ModifiedCount > 0, err
}



// 软删除
func (m *GoodsModel) Delete(id string) (deleted bool, err error) {
	coll := global.Mongo.Collection(TABLE_NAME_GOODS)
	_id, _ := primitive.ObjectIDFromHex(id)
	updateFields := bson.M{}
	updateFields["deleted"] = true
	update := bson.M{
		"$set": updateFields,
	}
	res, err := coll.UpdateByID(context.TODO(), _id, update)
	return res.ModifiedCount > 0, err
}


// 查询一个
func (m *GoodsModel) GetOne(id string) (goodsModel *GoodsModel, err error) {
	coll := global.Mongo.Collection(TABLE_NAME_GOODS)
	_id, _ := primitive.ObjectIDFromHex(id)
	filter := bson.M{"_id": _id, "deleted": false}
	err = coll.FindOne(context.TODO(), filter).Decode(&goodsModel)
	return
}


  • services/goods.service.go
package services

import (
	"goRESTApiGen-goods/models"
	"github.com/imoowi/goRESTApiGen/util/response"
)
var goodsModel *models.GoodsModel
type GoodsService struct {
	
}

// 列表
func (s *GoodsService) List(searchKey string, page int64, pageSize int64) (pages response.Pages, res []*models.GoodsModel) {
	pages, res = goodsModel.List(searchKey, page, pageSize)
	return
}

// 添加
func (s *GoodsService) Add(_goodsModel *models.GoodsModel) (newId string, err error) {
	newId, err = goodsModel.Add(_goodsModel)
	return
}


// 修改
func (s *GoodsService) Update(_goodsModel *models.GoodsModel) (updated bool, err error) {
	updated, err = goodsModel.Update(_goodsModel)
	return
}


// 删除
func (s *GoodsService) Delete(id string) (deleted bool, err error) {
	deleted, err = goodsModel.Delete(id)
	return
}

// 查询一个
func (s *GoodsService) GetOne(id string) (_goodsModel *models.GoodsModel, err error) {
	_goodsModel, err = goodsModel.GetOne(id)
	return
}


生成swagger接口如图

接下来会做什么?

如何给model添加hook?

项目地址

https://github.com/imoowi/goRESTApiGen