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"`
}
。。。 。。。 。。。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.