- Created by 郭强, last modified on Sep 30, 2022
该功能特性从v2.1
版本开始提供。
基本介绍
设计背景
在业务项目实践中,业务逻辑封装往往是最复杂的部分,同时,业务模块之间的依赖十分复杂、边界模糊,无法采用Golang
包管理的形式。如何有效管理项目中的业务逻辑封装部分,对于每个采用Golang
开发的项目都是必定会遇到的难题。
设计目标
- 增加
logic
分类目录,将所有业务逻辑代码迁移到logic
分类目录下,采用包管理形式来管理业务模块。 - 业务模块之间的依赖通过接口化解耦,将原有的
service
分类调整为接口目录。这样每个业务模块将会各自维护、更加灵活。 - 可以按照一定的项目规范,从
logic
业务逻辑代码生成service
接口定义代码。同时,也允许人工维护这部分service
接口。
命令使用
该命令通过分析给定的logic
业务逻辑模块目录下的代码,自动生成service
目录接口代码。
需要注意:
- 由于该命令是根据业务模块生成
service
接口,因此只会解析二级目录下的go
代码文件,并不会无限递归分析代码文件。以logic
目录为例,该命令只会解析logic/xxx/*.go
文件。因此,需要logic
层代码结构满足一定规范。 - 不同业务模块中定义的结构体名称在生成的
service
接口名称时可能会重复覆盖,因此需要在设计业务模块时保证名称不能冲突。
手动模式
如果是手动执行命令行,直接在项目根目录下执行 gf gen service
即可。
$ gf gen service -h USAGE gf gen service [OPTION] OPTION -s, --srcFolder source folder path to be parsed. default: internal/logic -d, --dstFolder destination folder path storing automatically generated go files. default: internal/service -f, --dstFileNameCase destination file name storing automatically generated go files, cases are as follows: | Case | Example | |---------------- |--------------------| | Lower | anykindofstring | | Camel | AnyKindOfString | | CamelLower | anyKindOfString | | Snake | any_kind_of_string | default | SnakeScreaming | ANY_KIND_OF_STRING | | SnakeFirstUpper | rgb_code_md5 | | Kebab | any-kind-of-string | | KebabScreaming | ANY-KIND-OF-STRING | -w, --watchFile used in file watcher, it re-generates all service go files only if given file is under srcFolder -a, --stPattern regular expression matching struct name for generating service. default: ^s([A-Z]\\w+)$ -p, --packages produce go files only for given source packages -i, --importPrefix custom import prefix to calculate import path for generated importing go file of logic -l, --clear delete all generated go files that are not used any further -h, --help more information about this command EXAMPLE gf gen service gf gen service -f Snake
参数说明:
名称 | 必须 | 默认值 | 含义 | ||||||
---|---|---|---|---|---|---|---|---|---|
srcFolder | 是 | internal/logic | 指向logic代码目录地址 | ||||||
dstFolder | 是 | internal/service | 指向生成的接口文件存放目录 | ||||||
dstFileNameCase | 否 | Snake | 生成的文件名名称格式 | ||||||
stPattern | 否 | s([A-A]\w+) | 使用正则指定业务模块结构体定义格式,便于解析业务接口定义名称。在默认的正则下,所有小写
| ||||||
watchFile | 用在代码文件监听中,代表当前改变的代码文件路径 | ||||||||
packages | 仅生成指定包名的接口文件,给定字符串数组,通过命令行传参则给定JSON 字符串,命令行组件自动转换数据类型 | ||||||||
importPrefix | 指定生成业务引用文件中的引用包名前缀 | ||||||||
overwrite | true | 生成代码文件时是否覆盖已有文件 | |||||||
clear | false | 自动删除logic 中不存在的接口文件(仅删除自动维护的文件) |
自动模式
如果您是使用的GolandIDE
,那么可以使用我们提供的配置文件:watchers.xml 自动监听代码文件修改时自动生成接口文件。使用方式,如下图:
具体使用手摸手
Step1:引入我们提供的配置
我们建议您在使用Goland IDE时,使用我们提供的配置文件:watchers.xml
Step2:编写您的业务逻辑代码
Step3:生成接口及服务注册文件
如果您已经按照Step1做好了配置,那么这一步可以忽略。因为在您编写代码的时候,service
便同时生成了接口定义文件。
否则,每一次在您开发/更新完成logic
业务模块后,您需要手动执行一下 gf gen service
命令。
Step4:注意服务的实现注入部分(仅一次)
只有在生成完成接口文件后,您才能在每个业务模块中加上接口的具体实现注入。该方法每个业务模块加一次即可。
Step5:在启动文件中引用接口实现注册(仅一次)
可以发现,该命令除了生成接口文件之外,还生成了一个接口实现注册文件。该文件用于在程序启动时,将接口的具体实现在启动时执行注册。
该文件的引入需要在main
包的最顶部引入,需要注意import
的顺序,放到最顶部,后面加一个空行。如果同时存在packed
包的引入,那么放到packed
包后面。像这样:
Step6:Start&Enjoy
启动main.go
即可。
常见问题FAQ
快速定位接口的具体实现
项目业务模块采用接口化解耦后体验非常棒!但是我在开发和调试过程中,想要快速找到指定接口的具体实现有点困难,能给点指导思路吗?
> 这里我推荐使用Goland IDE
,有个很棒的接口实现定位功能,具体如图。找到接口定义后,点击左边的小图标可快速定位具体的实现。如果Goland不显示小图标,可以尝试升级使用最新版本的Goland
哈。
- No labels
19 Comments
强仔
强仔
GF Version: v2.1.2 已经解决.
强仔
生成service的文件名全是小写,是不是应该与service保持一致.
fushen
针对这个问题有给强哥提了PR,希望能被合并~
https://github.com/gogf/gf/pull/1953
强仔
我看了代码,好像是刻意转成小写的呢.另外请教您一下.我测试时生成的service会一些用不到的包,这个您了解是什么问题吗?
fushen
强哥说是bug,目前可以通过 goimports 工具自动清理多出包。
强仔
GF Version: v2.1.2 已经解决.
强仔
生成service时,没有判断逻辑代码是否注释.即使注释的方法也会生成;
强仔
这里我推荐使用GolandIDE,有个很棒的接口实现定位功能,具体如图。找到接口定义后,点击左边的小图标可快速定位具体的实现。
Code generated by GoFrame CLI tool. DO NOT EDIT.
老大,这个要把生成的头部修改一下,小图标才能出现.有上边这个就没有小图标.
烧饵块
自定义目录,会提示:
source folder path "internal/logic" does not exist
wqliu129
郭强 强仔 郭老板 您的GolandIDE 什么版本的,我这没有你说的那个小图标呀?
wqliu129
强仔 把文件的
Code generated by GoFrame CLI tool. DO NOT EDIT. 删除了就有小图标了!
Numst
请问我用gf gen service 为什么生成不了service文件,都需要哪些步骤
logic 文件已经写好了
ll internal/logic/
drwxr-xr-x 3 root root 4096 Sep 16 17:18 ./
drwxr-xr-x 11 root root 4096 Sep 14 15:51 ../
drwxr-xr-x 2 root root 4096 Sep 16 17:18 camera_type/
gf gen service
done!
只是返回了done 然后就没了
servcice还是空的
keith
你的那个是手动执行,自动不香么。。。
但我的也是,怀疑是作者偷懒。你需要自己先写一下注入和接口名称,将接口和实现函数关联(就是类似java中的构造方法,我总是搞混,魔怔了),然后你改动logic中实现方法,就会自动自动创建service中接口,不需要每次都改。
Numst
谢谢回复,不用自动是因为电脑用goland占用内存太大,然后我这这边排查了下,发现问题有个logic的返回值少了一个空格,这可太难受了
gcf
请问如何将logic进行分组生产不同分组service?
当前gf gen logic仅可以对logic下面的儿子目录生产service,因为项目稍微大了之后,logic就需要进分组了,需要将某些逻辑分组生产不同的service进行保存。研究了半天没研究出来该怎么做。求破!
jangbx
有没有针对 vscode 的插件哦
surme
我在logic层的方法返回了一个errors.New("xxxx")这种的,会导致生成的service中多一行
但是这个引用在service文件中没有使用,打包的时候就会一直提示,当然可以手动删掉,但是每次生成又会从新出现
yudan215
如果在logic上继承了某个结构体,例如gf-jwt
生成出来的service并没有jwt.GfJWTMiddleware里面的方法,这样请问要如何解决?