该功能特性从v2.1版本开始提供。

该功能特性为实验性特性。建议开发者以logic下的模块划分为主,梳理模块间关联关系,避免循环依赖,充分利用Golang编译器的循环依赖检测特性编写更高质量的项目代码。

基本介绍

设计背景

在业务项目实践中,业务逻辑封装往往是最复杂的部分,同时,业务模块之间的依赖十分复杂、边界模糊,较难采用Golang包管理的形式。如何有效管理项目中的业务逻辑封装部分,对于每个采用Golang开发的项目都是必定会遇到的难题。

在标准的软件设计流程中,模块与模块之间的依赖会先明确接口定义,在软件开发的实施过程中再通过代码来具体实现。但在大部分高节奏的互联网工程下,并没有严谨的软件设计流程,甚至开发人员的质量水平也参差不齐,大部分开发人员首先关心的是如何去实现需求场景对应的功能逻辑,尽可能地提高开发效率。

设计目标

  1. 提供一种代码管理方式,可以通过具体模块实现直接生成模块接口定义、模块注册代码。
  2. 简化业务逻辑实现与接口分离的实现,降低模块方法与接口定义的重复操作,提高模块与模块之间的透明度与调用便捷性。

设计实现

  1. 增加logic分类目录,将所有业务逻辑代码迁移到logic分类目录下,采用包管理形式来管理业务模块。
  2. 业务模块之间的依赖通过接口化解耦,将原有的service分类调整为接口目录。这样每个业务模块将会各自维护、更加灵活。
  3. 可以按照一定的编码规范,从logic业务逻辑代码生成service接口定义代码。同时,也允许人工维护这部分service接口。

注意事项

再次提醒,通过logic实现去生成service接口并不是一个代码管理的标准化做法,只是提供另一个可供选择的、便捷的代码管理方式。这种管理方式有优点也有缺点,优点是针对微服务场景的业务模块的接口自动生成比较方便;缺点是无法识别语法继承关系、无法生成父级嵌套类型的方法、抛弃了Golang编译时检测循环依赖的特性。

框架的工程管理当然也支持标准的接口代码管理方式,即支持先定义service接口,再编码logic具体实现。需要注意的是,这个service的源代码中不能出现顶部工具的注释信息(工具依靠这个注释来判断该文件是否可覆盖😈),很多同学复制粘贴的时候把文件顶部注释保留了,就会引起手动维护接口文件失效。具体见截图注释:

模块规范-gen service - 图1

命令使用

该命令通过分析给定的logic业务逻辑模块目录下的代码,自动生成service目录接口代码。

需要注意:

  1. 由于该命令是根据业务模块生成service接口,因此只会解析二级目录下的go代码文件,并不会无限递归分析代码文件。以logic目录为例,该命令只会解析logic/xxx/*.go文件。因此,需要logic层代码结构满足一定规范。
  2. 不同业务模块中定义的结构体名称在生成的service接口名称时可能会重复覆盖,因此需要在设计业务模块时保证名称不能冲突。

该命令的示例项目请参考:https://github.com/gogf/gf-demo-user

手动模式

如果是手动执行命令行,直接在项目根目录下执行 gf gen service 即可。

  1. $ gf gen service -h
  2. USAGE
  3. gf gen service [OPTION]
  4. OPTION
  5. -s, --srcFolder source folder path to be parsed. default: internal/logic
  6. -d, --dstFolder destination folder path storing automatically generated go files. default: internal/service
  7. -f, --dstFileNameCase destination file name storing automatically generated go files, cases are as follows:
  8. | Case | Example |
  9. |---------------- |--------------------|
  10. | Lower | anykindofstring |
  11. | Camel | AnyKindOfString |
  12. | CamelLower | anyKindOfString |
  13. | Snake | any_kind_of_string | default
  14. | SnakeScreaming | ANY_KIND_OF_STRING |
  15. | SnakeFirstUpper | rgb_code_md5 |
  16. | Kebab | any-kind-of-string |
  17. | KebabScreaming | ANY-KIND-OF-STRING |
  18. -w, --watchFile used in file watcher, it re-generates all service go files only if given file is under
  19. srcFolder
  20. -a, --stPattern regular expression matching struct name for generating service. default: ^s([A-Z]\\w+)$
  21. -p, --packages produce go files only for given source packages
  22. -i, --importPrefix custom import prefix to calculate import path for generated importing go file of logic
  23. -l, --clear delete all generated go files that are not used any further
  24. -h, --help more information about this command
  25. EXAMPLE
  26. gf gen service
  27. gf gen service -f Snake

如果使用框架推荐的项目工程脚手架,并且系统安装了make工具,也可以使用make service快捷指令。

参数说明:

名称必须默认值含义
srcFolderinternal/logic指向logic代码目录地址
dstFolderinternal/service指向生成的接口文件存放目录
dstFileNameCaseSnake生成的文件名名称格式
stPatterns([A-A]\w+)

使用正则指定业务模块结构体定义格式,便于解析业务接口定义名称。在默认的正则下,所有小写s开头,大写字母随后的结构体都将被当做业务模块接口名称。例如:

logic结构体名称service接口名称
sUserUser
sMetaDataMetaData
watchFile

用在代码文件监听中,代表当前改变的代码文件路径

packages

仅生成指定包名的接口文件,给定字符串数组,通过命令行传参则给定JSON字符串,命令行组件自动转换数据类型
importPrefix

指定生成业务引用文件中的引用包名前缀
overwrite
true生成代码文件时是否覆盖已有文件
clear
false自动删除logic中不存在的接口文件(仅删除自动维护的文件)

自动模式

Goland/Idea

如果您是使用的GolandIDE,那么可以使用我们提供的配置文件:watchers.xml 自动监听代码文件修改时自动生成接口文件。使用方式,如下图:

模块规范-gen service - 图2

Visual Studio Code

如果您是使用的Visual Studio Code,那么可以安装插件 RunOnSave 随后配置插件:

  1. "emeraldwalk.runonsave": {
  2. "commands": [
  3. {
  4. "match": ".*logic.*go",
  5. "isAsync": true,
  6. "cmd": "gf gen service"
  7. }
  8. ]
  9. }

具体使用手摸手

Step1:引入我们提供的配置

我们建议您在使用Goland IDE时,使用我们提供的配置文件:watchers.xml

Step2:编写您的业务逻辑代码

模块规范-gen service - 图3

Step3:生成接口及服务注册文件

如果您已经按照Step1做好了配置,那么这一步可以忽略。因为在您编写代码的时候,service便同时生成了接口定义文件。

否则,每一次在您开发/更新完成logic业务模块后,您需要手动执行一下 gf gen service 命令。

模块规范-gen service - 图4

Step4:注意服务的实现注入部分(仅一次)

只有在生成完成接口文件后,您才能在每个业务模块中加上接口的具体实现注入。该方法每个业务模块加一次即可。

模块规范-gen service - 图5

Step5:在启动文件中引用接口实现注册(仅一次)

可以发现,该命令除了生成接口文件之外,还生成了一个接口实现注册文件。该文件用于在程序启动时,将接口的具体实现在启动时执行注册。

模块规范-gen service - 图6

该文件的引入需要在main包的最顶部引入,需要注意import的顺序,放到最顶部,后面加一个空行。如果同时存在packed包的引入,那么放到packed包后面。像这样:

模块规范-gen service - 图7

Step6:Start&Enjoy

启动main.go即可。

常见问题FAQ

logic中的结构体存在嵌套时,无法自动生成嵌套类型的方法

这种场景建议手动维护service接口定义,不使用工具的自动生成。手动维护的接口定义文件不会被工具覆盖,手动和自动可以同时使用。

快速定位接口的具体实现

项目业务模块采用接口化解耦后体验非常棒!但是我在开发和调试过程中,想要快速找到指定接口的具体实现有点困难,能给点指导思路吗?

> 这里我推荐使用Goland IDE,有个很棒的接口实现定位功能,具体如图。找到接口定义后,点击左边的小图标可快速定位具体的实现。如果Goland不显示小图标,可以尝试升级使用最新版本的Goland哈。

模块规范-gen service - 图8

或者在左侧没有小图标的时候,可以右键选择 Go To → Implementation(s)

模块规范-gen service - 图9