Gingo
Introduce
Gingo是基于 gin 框架为外围的脚手架,可能疾速创立Restful格调的API接口,并且能提供简略的后盾治理性能,应用本我的项目能够疾速实现业务逻辑开发。
Github: https://github.com/songcser/gingo
Feature
- gin框架,简略,高效,轻量
- gorm数据库ORM框架,封装mapper,应用简略
- viper配置管理
- zap日志框架,输入日志更灵便
- api接口封装,疾速实现CURD操作,提供Restful格调接口
- admin后盾治理,实现了简略的后盾治理,不便进行数据管理
- 应用范型,go版本不能低于1.18
Catalogue
.|——.gitignore|——go.mod|——go.sum|——cmd └──migrate └──main.go // 注册数据库表 └──main.go // 我的项目入口main|——README.md|——config // 配置文件目录| └──autoload // 配置文件的构造体定义包| └──admin.go // admin配置| └──db.go| └──jwt.go // jwt配置| └──mysql.go // mysql配置| └──zap.go // zap日志配置| └──config.yaml // .yaml配置示例文件| └──config.go // 配置初始化文件|——initialize // 数据初始化目录| └──admin.go // admin初始化| └──constants.go // 常量数据| └──gorm.go // 数据库初始化| └──mysql.go // mysql初始化| └──router.go // gin初始化| └──swagger.go | └──viper.go // viper配置初始化| └──zap.go // zap日志初始化|——internal // 该服务所有不对外裸露的代码,通常的业务逻辑都在这上面,应用internal防止谬误援用|──middleware // 中间件目录| └──logger.go // 日志中间件,打印申请数据| └──recovery.go // 自定义recovery, 输入谬误格式化|──pkg // 外部服务包 | └──admin // admin实现逻辑| └──admin.go| └──init.go| └──model.go| └──service.go| └──api // API接口封装| └──api.go| └──auth // 登陆受权接口封装| └──model.go | └──user.go | └──model // 底层模型封装| └──mapper.go | └──model.go | └──page.go | └──wrapper.go | └──response // 响应数据模型封装| └──page.go | └──response.go | └──router // 路由模块封装| └──router.go | └──service // 服务模块封装| └──service.go|──templates // admin模版页面| └──add.html // 新建页面| └──edit.html // 编辑页面| └──embed.go | └──header.html // 头部页面| └──home.html // 首页| └──index.html // 主页面| └──login.html // 登陆页面| └──register.html // 注册页面页面| └──sidebar.html // 右边栏页面|──utils // 一些工具办法| └──cache.go // 缓存| └──error.go // error查看| └──hash.go // hash加密解密| └──http.go // http客户端申请| └──json.go // | └──jwt.go // JWT| └──path.go // 文件门路| └──time.go // time相干办法| └──translator.go // 中英文翻译
Usage
internal目录是不对外裸露的代码,在做go get时,此目录不会被下载,所以通常业务逻辑放在这个上面。
咱们将在这个目录上面加一些业务代码,阐明脚手架的应用。
在internal目录下新增 app 包目录
Model
// Package app model.gopackage appimport "github.com/songcser/gingo/pkg/model"type App struct { model.BaseModel Name string `json:"name" gorm:"column:name;type:varchar(255);not null"` Description string `json:"description" gorm:"column:description;type:varchar(4096);not null"` Level string `json:"level" gorm:"column:level;type:varchar(8);not null"` Type string `json:"type" gorm:"column:type;type:varchar(16);not null"`}
App模型有4个自定义字段,gorm标签会对应到数据库的字段。
package modeltype Model interface { Get() int64}type BaseModel struct { ID int64 `json:"id" gorm:"primarykey" admin:"disable"` // 主键ID CreatedAt utils.JsonTime `json:"createdAt" gorm:"index;comment:创立工夫" admin:"disable"` // 创立工夫 UpdatedAt utils.JsonTime `json:"updatedAt" gorm:"index;comment:更新工夫" admin:"disable"` // 更新工夫}func (m BaseModel) Get() int64 { return m.ID}
BaseModel 是根底模型,有一些公共字段, 并且实现了 Model interface, 所有援用 BaseModel 的模型都实现了 Model interface。
创立数据库表
# Package initialize gorm.gopackage initialize// RegisterTables 注册数据库表专用func RegisterTables(db *gorm.DB) { err := db.Set("gorm:table_options", "CHARSET=utf8mb4").AutoMigrate( // 零碎模块表 auth.BaseUser{}, app.App{}, // app表注册 ) if err != nil { os.Exit(0) }}
执行 migrate 的 main 办法会在数据库创立对应的表。
Api
// Package app api.gopackage appimport ( "github.com/songcser/gingo/pkg/api" "github.com/songcser/gingo/pkg/service")type Api struct { api.Api}func NewApi() Api { var app App baseApi := api.NewApi[App](service.NewBaseService(app)) return Api{baseApi}}
api.Api接口
// Package api api.gopackage apiimport "github.com/gin-gonic/gin"type Api interface { Query(c *gin.Context) Get(c *gin.Context) Create(c *gin.Context) Update(c *gin.Context) Delete(c *gin.Context)}
api.Api接口定义了CURD办法,并且办法都是gin.HandlerFunc类型,能够间接绑定到gin Router上。
BaseApi实现了CURD的根本办法,app.Api类型组合了BaseApi的办法。
Router
// Package app router.gopackage appimport ( "github.com/gin-gonic/gin" "github.com/songcser/gingo/pkg/router")func InitRouter(g *gin.RouterGroup) { r := router.NewRouter(g.Group("app")) a := NewApi() r.BindApi("", a)}
router 是对gin.RouterGroup做了简略封装,不便和Api类型做绑定。
BindApi办法将Api的 CURD 办法和router进行了绑定。
启动服务之后,执行脚本或者应用 postman 申请服务
创立数据
curl --location 'http://localhost:8080/api/v1/app' \--header 'Content-Type: application/json' \--data '{ "name": "测试利用", "description": "测试应用服务", "level": "S3", "type": "container"}'
返回内容
{ "code": 0, "data": true, "message": "success"}
胜利创立数据
查问数据
curl --location 'http://localhost:8080/api/v1/app'
返回内容
{ "code": 0, "data": { "total": 1, "size": 10, "current": 1, "results": [ { "id": 1, "createdAt": "2023-04-13 16:35:59", "updatedAt": "2023-04-13 16:35:59", "name": "测试利用", "description": "测试应用服务", "level": "S3", "type": "container" } ] }, "message": "success"}
查问单个数据
curl --location 'http://localhost:8080/api/v1/app/1'
返回内容
{ "code": 0, "data": { "id": 1, "createdAt": "2023-04-13 16:56:09", "updatedAt": "2023-04-13 16:58:29", "name": "测试利用", "description": "测试应用服务", "level": "S3", "type": "container" }, "message": "success"}
更新数据
curl --location --request PUT 'http://localhost:8080/api/v1/app/1' \--header 'Content-Type: application/json' \--data '{ "name": "测试利用", "description": "测试应用服务", "level": "S1", "type": "container"}'
返回内容
{ "code": 0, "data": true, "message": "success"}
删除数据
curl --location --request DELETE 'http://localhost:8080/api/v1/app/1'
返回内容
{ "code": 0, "data": true, "message": "success"}
自定义办法
api增加新的办法
// Package app api.gopackage appfunc (a Api) Hello(c *gin.Context) { response.OkWithData("Hello World", c)}
router进行绑定
r.BindGet("hello", a.Hello)
接口申请
curl --location 'http://localhost:8080/api/v1/app/hello'
返回内容
{ "code": 0, "data": "Hello World", "message": "success"}
Service
在 NewApi 时应用的是BaseService,能够实现自定义的Service,重写一些办法。
package appimport ( "github.com/gin-gonic/gin" "github.com/songcser/gingo/pkg/model" "github.com/songcser/gingo/pkg/service" "github.com/songcser/gingo/utils")type Service struct { service.Service[App]}func NewService(a App) Service { return Service{service.NewBaseService[App](a)}}func (s Service) MakeMapper(c *gin.Context) model.Mapper[App] { var r Request err := c.ShouldBindQuery(&r) utils.CheckError(err) w := model.NewWrapper() w.Like("name", r.Name) w.Eq("level", r.Level) m := model.NewMapper[App](App{}, w) return m}func (s Service) MakeResponse(val model.Model) any { a := val.(App) res := Response{ Name: a.Name, Description: fmt.Sprintf("名称:%s, 等级: %s, 类型: %s", a.Name, a.Level, a.Type), Level: a.Level, Type: a.Type, } return res}
- MakeMapper办法重写新的Mapper,能够自定义一些查问条件。
- MakeResponse办法能够重写返回的内容
在Api中替换新的Service
// Package app api.gofunc NewApi() Api { var app App s := NewService(app) //应用新的Service baseApi := api.NewApi[App](s) return Api{Api: baseApi}}
查问数据
curl --location 'http://localhost:8080/api/v1/app?name=测试&level=S3'
返回内容
{ "code": 0, "data": { "total": 1, "size": 10, "current": 1, "results": [ { "name": "测试利用", "description": "名称:测试利用, 等级: S3, 类型: container", "level": "S3", "type": "container" } ] }, "message": "success"}
如果要在Service减少新的办法,须要在Api模型中重写Service
// Package app service.gofunc (s Service) Hello() string { return "Hello World"}
Api实现
// Package app api.gopackage apptype Api struct { api.Api Service Service // 重写Service}func NewApi() Api { var app App s := NewService(app) baseApi := api.NewApi[App](s) return Api{Api: baseApi, Service: s}}func (a Api) Hello(c *gin.Context) { str := a.Service.Hello() // 调用Service办法 response.OkWithData(str, c)}
Admin
Admin 提供了简略的后盾治理服务,能够很不便的对数据进行治理。
首先须要在配置文件中开启 Admin
admin: enable: true auth: true
auth 会开启认证受权,须要登陆
接入 Admin 也比较简单
// Package app admin.gopackage appimport ( "github.com/songcser/gingo/pkg/admin")func Admin() { var a App admin.New(a, "app", "利用")}
在 initialize 中引入 admin
// Package initialize admin.gopackage initializefunc Admin(r *gin.Engine) { if !config.GVA_CONFIG.Admin.Enable { return } admin.Init(r, nil) app.Admin()}
在治理页面能够进行简略的查问,创立,批改,删除操作。
Model 字段中能够配置 admin 标签,治理页面能够依据类型展现。
// Package app model.gopackage appimport "github.com/songcser/gingo/pkg/model"type App struct { model.BaseModel Name string `json:"name" form:"name" gorm:"column:name;type:varchar(255);not null" admin:"type:input;name:name;label:利用名"` Description string `json:"description" form:"description" gorm:"column:description;type:varchar(4096);not null" admin:"type:textarea;name:description;label:形容"` Level string `json:"level" form:"level" gorm:"column:level;type:varchar(8);not null" admin:"type:radio;enum:S1,S2,S3,S4,S5;label:级别"` Type string `json:"type" form:"type" gorm:"column:type;type:varchar(16);not null" admin:"type:select;enum:container=容器利用,web=前端利用,mini=小程序利用;label:利用类型"`}
- type: 字段类型,取值 input, textarea, select, radio。
- name: 字段名称
- label: 字段展现名称
- enum: 枚举数据,在select,radio类型时展现更加敌对
须要增加 form 标签,因为是应用 html 的 form 提交数据。
拜访链接
http://localhost:8080/admin/
首页
点击利用,查看利用列表
点击 创立利用 按钮