Gen Web - 基于 Gin 框架封装的脚手架结构,便于快速开发 API
https://github.com/wangbjun/gen
主要使用以下开源组件:
项目目录结构清晰明了,简单易用,快速上手,包含了一个用户注册、登录、文章增删改查等功能的 Restful API 应用,仅供参考!
主要包含以下 API:
METHOD | URI | DESCRIPTION |
---|---|---|
GET | / | 默认首页 |
POST | /api/v1/user/register | 用户注册 |
POST | /api/v1/user/login | 用户登录 |
POST | /api/v1/user/logout | 用户登出 |
GET | /api/v1/articles | 文章列表 |
POST | /api/v1/articles | 发布文章 |
GET | /api/v1/articles/:id | 文章详情 |
PUT | /api/v1/articles/:id | 修改文章 |
DELETE | /api/v1/articles/:id | 删除文章 |
POST | /api/v1/articles/:id/comments | 添加文章评论 |
项目采用了依赖注入的方式贯穿全局,我们可以把 DB 、缓存、HTTP API 等功能看作是项目的一个服务,通过 facebook 开源的 inject 库,我们在启动项目把这些Service
注入进去,解决各自之间的依赖关系。
type ArticleService struct {
SQLStore *SQLService `inject:""`
Cache *cache.CacheService `inject:""`
}
func init() {
registry.RegisterService(&ArticleService{})
}
func (r ArticleService) Init() error {
return nil
}
既灵活,也不影响性能,因为虽然依赖注入使用了反射,但是我们只在程序启动之前做这件事,而且只需要进行一次。
main
文件是程序的入口,主要功能是解析命令行参数,只有一个参数,那就是配置文件,默认配置文件是当前目录下的app.ini
紧接着,创建一个Server
实例:
// Server is responsible for managing the lifecycle of services.
type Server struct {
context context.Context
shutdownFn context.CancelFunc
childRoutines *errgroup.Group
log *zap.Logger
cfg *config.Cfg // 项目配置
shutdownOnce sync.Once
shutdownFinished chan struct{}
isInitialized bool
mtx sync.Mutex
serviceRegistry serviceRegistry // 注册的服务
}
这个 Server 实例是管理所有服务的中心,其主要工作就是加载配置文件,然后根据配置文件初始化日志配置,日志库采用 zap log,主要文件在zap/zap_logger.go
里面
然后还有一个最重要是就是初始化所有注册过服务,执行其Init
方法做一些初始化工作,最后执行后台服务。
如果一个服务实现了Run
方法,就是一个后台服务,会在项目启动时候运行,结束时候优雅关闭,其中最好的例子就是HTTPServer
,我们可以把 API 服务认为是一个后台服务,在整个项目启动的时候就会运行。
type HTTPServer struct {
log *zap.Logger
gin *gin.Engine
context context.Context
Cfg *config.Cfg `inject:""`
ArticleService *article.ArticleService `inject:""`
UserService *user.UserService `inject:""`
}
HTTPServer 的代码在api/http_server.go
文件里面,其主要作用就是初始化一些服务配置,然后启动 HTTP 服务,使用了 Gin 框架。
在services
文件夹下包含了一些服务的代码文件。
项目整体是一个 3 层架构,即控制器层、Service 层、模型层。
个人理解,控制器层主要做一些接口参数校验等工作,模型层主要是数据操作,Service 层才是主要的业务逻辑。
数据库相关配置在models/db.go
里面,也是一个服务,主要作用是根据配置,初始化数据库连接,支持多数据库配置。
type SQLService struct {
Cfg *config.Cfg `inject:""`
conns map[string]*gorm.DB
log *zap.Logger
}
func DB(dbName ...string) *gorm.DB {
if len(dbName) > 0 {
if conn, ok := sqlStore.conns[dbName[0]]; ok {
return conn
}
}
return db
}
项目使用了 Gorm ( 2.0 版本),具体详细用法可以参考官方文档。
路由文件位于api/api.go
,可以多层嵌套,中间件在middleware
文件夹。
config/config.go
是配置文件的一些加载逻辑,可以根据自己需求适当的修改优化。
关于接口参数,建议 POST 、PUT 统一使用 JSON 形式,在模型层里面定义好相应的结构体,参数的校验采用了go-playground/validator/v10
库,直接在结构体 Tag 里面标记即可,详细用法请参考其官方文档。
type CreateArticleCommand struct {
Id int
UserId int
Title string `form:"title" json:"title" binding:"gt=1,lt=100"`
Content string `form:"content" json:"content" binding:"gt=1,lt=2000"`
}
type UpdateArticleCommand struct {
Id int
UserId int
Title string `form:"title" json:"title" binding:"gt=1,lt=100"`
Content string `form:"content" json:"content" binding:"gt=1,lt=2000"`
}
。。。 。。。 。。。
1
wandehul 2021-06-24 00:51:39 +08:00 1
先 mark,刚好最近有这方面的需求,等这一阵手里的活忙完了,再看
|
2
quzard 2021-06-24 08:52:29 +08:00 via Android
学习了。自己也写一个
|
3
JustSong 2021-06-24 12:13:50 +08:00 via Android
建议设成 template
|
4
honkki 2021-06-24 13:16:18 +08:00
log 能打印 sql 语句吗
|
5
wangbenjun5 OP @honkki 可以
|
6
abccccabc 2021-06-24 16:56:39 +08:00
@wangbenjun5 你是怎么学 go 的?? 好厉害呀, 给新手一个学习提纲如何?
|
7
WhereverYouGo 2021-06-24 20:05:37 +08:00
@abccccabc #6 自己做个小项目。换了家公司,从 Java 转 Go,进来先自己做个小项目,你做着做着就都会了[都是泪]
|