众所周知,Golang非常适合用于开发高性能的API,开源的Web框架也很多,比如国产的Beego,以及在目前最流行的Gin,还有Echo、Iris、Revel等框架。
由于博主之前从事过PHP,相比来说,感觉Go的这些框架都比较轻量,很多时候还需要自己花点功夫再打理一下,比如这些框架都没有处理数据库这块,Beego虽然自带了一个ORM,但是可用性极差,需要我们自己手动去集成一些开源的组件。
就拿我用过比较多的Gin框架( https://github.com/gin-gonic/gin )来说,它属于其中最轻量级的框架,主要功能包括路由、请求参数、中间件、模板等,存在一些缺失的东西,比如:
没有推荐项目结构模块划分,很多人不知道代码咋存放
缺少数据库ORM,虽说Go标准库支持数据库,但是缺少封装,用起来麻烦
缺少配置文件加载功能,任何项目都少不了配置文件
日志处理功能不够强大
所以,我基于Gin加上一些开源的组件,封装了一个不算是框架的框架,这里暂且称其为Gen,主要是便于快速开发,解决一些通用性的问题。
地址:https://github.com/wangbjun/gen
1.项目结构
这里参考借鉴了PHP的Web框架 Laravel 的结构,整体上是一个MVC结构:
基本上包含一个Web框架应该有的东西,包括路由、控制器层、模型层、service层等,便于我们存放代码,开发起来也方便很多,通过文件夹名字我们就能了解各个包的主要作用。
项目使用Go Mod解决依赖,接下来我依次介绍一些主要模块的功能
2.Main入口
1 | package main |
main里面第一步就是加载配置文件,然后根据配置文件设置Gin的模式以及服务监听的端口,然后这里还有一些”隐藏“的init初始化操作,比如在初始化路由的过程中加载了数据库配置并且建立数据库连接、还有初始化日志配置等,具体可以查看各个包的init函数。
3.配置文件
默认配置文件是同级目录下的 app.ini,这里采用了gopkg.in/ini.v1
开源库解析配置,格式也是非常简单的k-v格式,举个例子:
1 | [APP] |
加载配置文件的代码位于config/Config.go
文件里面,逻辑非常简单,也支持通过”-c“指定配置文件,这里定义了一个包全局变量,一次加载,终身使用,具体的日志读取API可以参考这个库的官方文档。
4.日志处理
日志这块采用了来自uber的 zap 库,高性能,扩展性也很强,代码位于zlog/ZapLogger.go
文件,主要操作是根据加载的配置文件初始化日志级别、存储位置、存储格式以及自动分割等配置。
默认情况下,日志存储在storage/logs
文件夹下,格式是JSON
日志这块有一个特殊的功能,可以选择为每个日志加上traceId,便于追踪排查问题,核心代码如下:
1 | func getContext(ctx *gin.Context) []zap.Field { |
如果想记录当前请求的一些信息可以使用zlog.WithContext(ctx).Sugar().Infof("log msg")
这种写法来记录,同理,详细API可以参考其官方文档。
5.数据库处理
这里采用了知名的gorm开源库,数据库的配置在Conf/Database.go
里面,这里可以定义多个数据库配置:
1 | package config |
然后在model/DB.go
文件里面,初始化了所有的DB配置,并且提供一个快速访问的函数:
1 | // 获取默认db |
关于gorm的详细用法可以参考其官方文档:https://gorm.io/
6.其它
middleware文件夹里面主要一些中间件,比如说用户鉴权、请求日志的中间件,使用的时候需要在路由里面配置,这个可以参考Gin框架文档。
目前我的习惯是MVC+Service这套结构(纯api的话就没有V了),不过如果业务逻辑简单,直接全写在控制器里面也没多大问题。但是如果使用这套结构一定要注意划分好代码层次,不要出现相互引用的情况,比如说model包使用controller包定义的东西,然后controller又使用了model包里面的东西,这样的写法在PHP里面没问题,但是在Go里面无法通过编译。
所以,从最佳实践上说,应该是controller调model,model调service这个顺序,不可反向操作。
最后,这个项目自带了一个包括用户注册登录以及发表文章、查看文章的API的功能,具体可以查看项目README文件,如果想使用的话建议直接clone本项目,然后在这个基础上修改。