视频的第26分钟开始,演示了如何用脚本生成适合你自己的项目。

这个脚手架工程定位于支持企业级、要求一定弹性、业务逻辑较为复杂的应用开发。绝对不敢自称“最佳实践”,但以此为目标。

此示例包含:

  1. 企业级应用的分层架构
  2. gin + 最新版gorm的示例 (gorm2相对于jinzhu包的第一版gorm)
  3. 四个middleware
    1.1 cors
    1.2 authentication
    1.3 log
    1.4 error message
  4. ldap 登录功能
  5. 支持持久存储的postgre sql docker脚本
  6. 基于sqlite的自动化测试
  7. 初始化/客户化脚本,帮助一键生成适用于你的初始项目

一些关于技术的选择

1. 分层

分层的思想参照了Domain Driven Design的想法以及Robert. C.Martin的clearn architecture理论。这两个理论本质上几乎一样。DDD建议midtier分为controll层,service层和infrastructure层,代码的package基本也是以此为依据组织的。强烈推荐下面这本介绍DDD的书,对我有洗髓锻骨的功效。

网上有电子版,为避免被举报,请大家自行搜索下载或购买原版。

2. 数据库主键

这个工程使用了uuid作为主键生成机制。另外可以选择自增主键或者snowflake。

自增主键适合单机数据库,并且没有合并表需求的情况。顺序插入数据对排序也比较有利。如果涉及数据分片,或者有导入外部数据这样的需求,就不适合自增主键了,可以考虑uuid。自增主键另有一个令人诟病的地方,客户端可以通过主键推测业务规模。假如你吹牛业务挺大,有100万用户,人家新注册一个用户,发现主键是20,那就尴尬了。多数情况下,uuid足以支撑业务。snowflake 介于两者之间,在上面两个方案都不适合时,可以考虑snowflake,适合大数据,分布式结构,对查询性能要求很高的应用。

自增优点:

    • 存储空间小
    • 查询效率高

uuid优点:

    • 分布式友好
    • 避免暴露业务规模

3. 返回值struct vs. pointer

方法返回值应该用struct还是pointer?如果你问100个人,99个人会回答,返回数据大就用pointer,否则用struct。这种答案没有实操性,多大算大?参考了很多商业以及免费开源项目,找不到让自己满意的答案,直到看到了这篇文章:https://www.ardanlabs.com/blog/2014/12/using-pointers-in-go.html

在应用开发中,返回值通常不是primitive的简单值,这种情况一律用pointer. 方法的参数一律用值传递,除非数据太大(多大算大请自行体会,反正Martin Fowler说premature optimization is the root of all evils.),或者想要在方法中暴露参数数据的改变。

4. 尽量避免在运行时创建实例

实例应该在main函数中创建好,避免在程序运行时创建实例,否则容易出现race condition的问题。可以参考main.go中的做法。

5. ldap

6. 运行在docker中的postgre sql

是否用docker只是个人喜好,我倾向于用docker,因为很方便。有了docker,再也不用装各种数据库了,什么postgre sql, my sql, mongo db,我统统都放在docker里。

7. 命名规范

命名method时,不需要指定struct已经包含的信息。比如postRepository的add方法,肯定是addPost。

8. 自动化测试

如果业务逻辑跟数据库中已存储的数据相关度比较高,mock数据库的意义就不大了。因为如果mock的程序一跑都能跑通,而用了真正的数据库时,程序出一堆错,那么自动化测试就没什么意义了。所以我使用sqlite内存数据库做自动化测试。mock数据库不一定是错,并且也不是唯一的选择。可以依据你项目的特点来决定是否mock数据库。

9. 企业级开发的一些习惯

log的技术虽然很简单,但是log在业务上很重要。有时客户遇到问题,你没法在自己的环境中复现,这时就需要通过log来缩小或定位问题出现的位置。需要养成打印debug log的习惯。示例在中间件里使用了logrus打印来自客户端的信息,在应用中,也有一些位置使用了logrus. 这里log支持根据时间rotate。

应用需要有友好的报错信息和正确的http status code.

Rest API返回的payload,最好带有links, 对restful客户端比较友好。

10. 一条命令生成自己的应用

这个示例的名称是blog,唯一的entity是post。post这个字眼出现在文件名,以及很多代码文件内容中。可以修改替换scripts/reborn.sh中,new-text字符串为适合你的项目的string,然后运行reborn.sh,就可以瞬间生成你需要的应用。