Categorygithub.com/chenxinqun/ginWarp
repository
0.0.0-20230219180446-60317830eff2
Repository: https://github.com/chenxinqun/ginwarp.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# README

ginWarp

一个基于gin框架二次封装的框架

技术背景

ginWarp 框架是基于 gin框架 的二开

主要参考项目是gin的二开项目 go-gin-api

底层基于gin和gorm. 相关问题都可以找到开源方案. 我只整改了上层代码, 改变了使用方式.

相对 go-gin-api ,主要不同点在于,这是一个非侵入式框架.

同时做了许多裁剪, 包含的内容不如 go-gin-api 全面.

ginWarp

Go Get 使用 ginWarp


# 包名 github.com/chenxinqun/ginWarp
go get -u github.com/chenxinqun/ginWarp

ginWarp 程序启动流程与代码开发流程

  1. main函数引用 github.com/chenxinqun/ginWarp/coreServer 包, 调用 coreServer.StartHttpServer(nil, router.SetApiRouter), 传入自己写的 router.SetApiRouter 函数注册路由
  2. StartHttpServer 会内置两个命令行参数, 一个 env, 用来指定环境变量加载不同的配置文件, 默认为dev开发环境; 一个 addr, 传入一个带冒号的端口号, 指定监听地址, 默认为 :8888.
  3. StartHttpServer 会调用server/init.go 中的一些列初始化函数, 对配置文件以及各种数据库连接进行初始化
  4. 初始化完数据库之后, 调用传入的 router.SetApiRouter 函数, 注册路由
  5. 开发人员自己在 router.SetApiRouter 中, 将 handlers中的HandlerFunc注册成URL.
  6. 开发人员在 ./internal/api 中根据MVC分层自己实现业务逻辑.
  7. ginWarp 提供了MVC的代码生成工具, 可以参考 github.com/chenxinqun/zhcorectl 的使用文档
  8. 所有的Repo连接, 都有一个Default()函数, 可以对默认Repo连接进行获取, 在service中可以引用相应的repo所在包进行使用. 如: mysql.Default(), redis.Default(), mongo.Default()

ginWarp/example/api 目录中有一个简单的MVC示例, 包含上传文件, MySQL的修改查询与创建. 可以作为参考. example的main函数在 cmd/example中

工程目录结构


ginWarp
├─cmd                            // 存放一些main文件
│  ├─example                     // ginWarp/example 的启动目录
│  └─pushconfig                  // 启动 ginWarp/example 所需的配置文件
├─configs                        // 配置文件以及处理配置项的代码
├─docs                           // 文档目录
├─example                        // 一些框架使用的简单例子, 对等internal/目录.
│  ├─api                         
│  │  ├─handlers                 
│  │  │  └─userHandler           
│  │  ├─repository               
│  │  │  ├─mongoRepo             
│  │  │  ├─mysqlRepo             
│  │  │  │  └─usersRepo          
│  │  │  └─redisRepo             
│  │  └─services                 
│  │      └─userService          
│  └─router                     
├─internal                       // 业务内部包, 项目内部业务逻辑实现(业务代码)
│  ├─api                         // 存放 mvc 代码
│  │  ├─handlers                 // handlers层
│  │  ├─repository               // model层
│  │  └─services                 // service层
│  ├─pkg                         // 业务相关公共包
│  └─router                      // 路由注册
├─middleware                     // 一些全局的中间件
├─pkg                            // 公共包, 与业务关联较小,或多个业务可用,以及可以被别的项目所引用的包
│  ├─core                        // 关于Gin引擎的一些封装, 以及内置路由的一些定义
│  ├─coreServer                  // http服务启动与停止的一些封装
│  ├─ginWarpExampleApi           // 关于ginWarp/example项目用到的url的一些定义.
│  ├─ginWarpExampleCode          // 示例代码 ginWarp/example 用到的一些URL, request, response以及Client的定义
│  ├─ginWarpExampleRedis         // 示例代码 ginWarp/example 用到的一些业务码
│  ├─session                     // 示例代码 ginWarp/example 用到的 关于redis调用的一些封装
│  └─urls                        // 关于url的公共定义
├─scripts                        // 存放一些脚本文件
├─server                         // 具体业务中才需要的目录, 主要是定义一些在coreServer包中所用到的init与close方法
└─testing                        // 黑盒测试的测试用例存放目录
             

功能使用教程

参数验证器

参数验证器已经在框架中集成了. 只需要在接收参数的结构体中增加响应的Tag就行了. 关键字使用binding:"" 需要先之的内容, 定义在binding:""之中. 如下图所示:


type CreateRequest struct {
Account string `json:"account" binding:"required,min=4,max=24"`
Pwd     string `json:"pwd" binding:"required,min=8,max=16"`
}

// binding是一个适用于Gin框架的开源验证器. 底层使用 github.com/go-playground/validator 验证器.
具体定义字段, 可以参考 github.com/go-playground/validator 的 文档 .

使用MySQL

MySQL连接使用全局变量, 在 github.com/chenxinqun/ginWarpPkg/datax/mysqlx 包中. 用以下函数可以获得: mysqlx.Default()

MySQL连接需要配合代码生成器生成的DAO层使用. 所有的传入DAO层执行SQL的conn, 统一使用 mysql.Default()获取.

如果要获取原生的gorm.DB 请使用 mysql.Default().GetDb().WithContext(ctx) 方法. 示例代码如下:

package userService

import (
	"github.com/chenxinqun/ginWarp/example/api/repository/mysqlRepo/usersRepo"
	"github.com/chenxinqun/ginWarp/pkg/ginWarpExampleApi"
	"github.com/chenxinqun/ginWarp/pkg/ginWarpExampleCode"

	"github.com/chenxinqun/ginWarpPkg/convert"
	"github.com/chenxinqun/ginWarpPkg/datax/mysqlx"
	"github.com/chenxinqun/ginWarpPkg/httpx/mux"
)

type CreateParams struct {
	Account string
	Passwd  string
}

type CreateResult struct {
	User *usersRepo.Users
}

// Create 创建用户
// @Author Test
// @Summary 创建用户
// @Description 创建用户
// @Handlers handlers/asset/userHandler
func (s *service) Create(ctx mux.Context, params *ginWarpExampleApi.UserCreateRequest) (ret *ginWarpExampleApi.UserCreateResponse, code int, err error) {
	ret = new(ginWarpExampleApi.UserCreateResponse)
	user := usersRepo.NewModel()
	user.Account = params.Account
	user.SetPassword(params.Pwd)
	user.SetLoginTime()
	// 全局MySQL连接
	repo := mysqlx.Default()
	// 已经封装了超时时间的请求专用context
	rctx := ctx.RequestContext()
	_, err = user.Create(rctx, repo)
	if err != nil {
		return nil, ginWarpExampleCode.UserCreateError, err
	}
	err = convert.StructToStruct(*user, ret)
	if err != nil {
		return nil, ginWarpExampleCode.UserCreateError, err
	}
	return
}


MySQL事务: 使用 dao.Transaction 传入一个ctx, 一个conn和一个事务函数. 如下所示:

dao := usersRepo.NewQueryBuilder()
// 全局MySQL连接
repo := mysqlx.Default()
// 已经封装了超时时间的请求专用context
rctx := ctx.RequestContext()
dao.Transaction(rctx, repo, func (tx *gorm.DB) error {
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'mysql' 而不是 'db')
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
// 返回任何错误都会回滚事务
return err
}

if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
return err
}

// 返回 nil 提交事务
return nil
})

kafka的使用

MySQL连接使用全局变量, 在 github.com/chenxinqun/ginWarpPkg/datax/kafkax 包中. 用一下四个函数, 可以分别获得: 消费者: kafka.DefaultConsumer() 消费组: kafka.DefaultConsumerGroup() 异步生产者: kafka.DefaultAsyncProducer() 同步生产者: kafka.DefaultProducer()

使用示例如下:

package main

import (
	"github.com/chenxinqun/ginWarpPkg/datax/kafkax"
	"github.com/chenxinqun/ginWarpPkg/errno"
	"github.com/chenxinqun/ginWarpPkg/sysx/environment"
)

type Topic struct {
	kafkax.Topic
	t string
}

func (t *Topic) String() (topic string) {
	topic = t.t
	return
}

func main() {
	t := &Topic{t: "test1"}
	kafkax.DefaultConsumerGroup().Consume([]kafkax.Topic{t}, func(msg *kafkax.ConsumerMessage) (error, bool) {
		if msg == nil {
			return errno.NewError("msg为空"), true
		}
		return nil, true
	})

}

Redis使用

MongoDB连接使用全局变量, 在 github.com/chenxinqun/ginWarpPkg/datax/redisx 包中. 用以下函数可以获得: redisx.Default() 任何操作都应该使用redis的interface封装. 使用示例如下:

// Get Set string
const (
DetailsKey = "details"
)

func UserCacheKey(userID int64) string {
return fmt.Sprintf("%s:%d", scrm_system_redis.CachePrefix, userID)
}

func SetUserDetails(ctx mux.Context, userID int64, val scrm_user_repo.ScrmUser) error {
key := UserCacheKey(userID)
data, err := json.Marshal(val)
if err != nil {
return err
}
return redisx.Default().HSet(ctx.RequestContext(), key, map[string]interface{}{DetailsKey: string(data)}).Err()
}

func GetUserDetails(ctx mux.Context, userID int64, result *scrm_system_api.UsersDetailsResponse) error {
key := UserCacheKey(userID)
data, err := redisx.Default().HGet(ctx.RequestContext(), key, DetailsKey).Result()
if err != nil {
return err
}
err = json.Unmarshal([]byte(data), result)
return err
}

// 发布
func (s *service) PostProve(ctx mux.Context, rawData []byte) (ret map[string]string, err error) {
resp := make(map[string]string)
resp["RawData"] = string(rawData)
respJson, err := json.Marshal(resp)
if err != nil {
return nil, err
}
err = redisx.Default().Publish(string(respJson))
if err != nil {
return nil, err
}
ret = resp
return
}

// 订阅
// SubscribeCallBackEvent 企业微信事件回调
func SubscribeCallBackEvent() (err error) {
err = redis.Default().Subscribe(func (msg *redis.Message) (e error) {
ret := make(map[string]string)
// 原始数据再msg.Payload里面
e = json.Unmarshal([]byte(msg.Payload), &ret)
if e != nil {
loggerx.Default().Error("json序列化时报错", zap.Error(e), zap.String("redis数据", msg.Payload))
return e
}
...
下面写业务
})
return
}