介绍自己搭的一个 Go Web 脚手架项目

2021-06-24 00:42:25 +08:00
 wangbenjun5

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"`
}

。。。 。。。 。。。

2528 次点击
所在节点    程序员
7 条回复
wandehul
2021-06-24 00:51:39 +08:00
先 mark,刚好最近有这方面的需求,等这一阵手里的活忙完了,再看
quzard
2021-06-24 08:52:29 +08:00
学习了。自己也写一个
JustSong
2021-06-24 12:13:50 +08:00
建议设成 template
honkki
2021-06-24 13:16:18 +08:00
log 能打印 sql 语句吗
wangbenjun5
2021-06-24 13:58:34 +08:00
@honkki 可以
abccccabc
2021-06-24 16:56:39 +08:00
@wangbenjun5 你是怎么学 go 的?? 好厉害呀, 给新手一个学习提纲如何?
WhereverYouGo
2021-06-24 20:05:37 +08:00
@abccccabc #6 自己做个小项目。换了家公司,从 Java 转 Go,进来先自己做个小项目,你做着做着就都会了[都是泪]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/785427

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX