最近在做毕设,前台做完了,现在要开始搭建后台系统了,而后台系统,又大多数是固定的模版。
所以为了方便摸鱼,顺便写一个可以 自动生成模版 的代码工具
开源地址:https://github.com/CocaineCong/fgen
1. 项目生成1.1 项目结构
目前只支持生成单体式的项目结构目录,后续会更新微服务分布式的目录生成
效果如下
那么首先,我现阶段所了解的项目目录结构是一下结构:
demo/├── api // 暴露出api接口,承接router转发的请求道service层├── cmd // 项目启动├── config // 配置文件存放├── consts // 定义常量├── loading // 加载配置├── middleware // 中间件├── repository //持久层│ ├── db // 数据库│ │ ├── dao // dao层│ │ └── model // 一些定义的 struct 模型│ └── redis // 缓存或是redis├── test // test测试文件├── pkg // 存放一些配置│ ├── e │ └── util ├── router // 路由 ├── types // 类型转换├── serializer // 一些序列化,将数据传送给前端└── service // 服务层
1.2 生成目录
传入 project 的 path 以及 path 的 name ,用一个数组将这些目录存起来,因为对于一些特殊的目录,还要生成二级目录,或者是一些必备的文件,比如说 config 目录下的 .yaml 文件。
func GenProject(projectPath, projectName string) error {if projectPath == "" {
projectPath = "./"}if projectName == "" {// 外层能保证不为空
projectName = "demo/"}
genApiPath := projectPath + projectName + "api/"
genCmdPath := projectPath + projectName + "cmd/"
genConfigPath := projectPath + projectName + "config/"
genConstsPath := projectPath + projectName + "consts/"
genLoadingPath := projectPath + projectName + "loading/"
genMiddlewarePath := projectPath + projectName + "middleware/"
genPkgPath := projectPath + projectName + "pkg/"
genRepositoryPath := projectPath + projectName + "repository/"
genRouterPath := projectPath + projectName + "router/"
genSerializerPath := projectPath + projectName + "serializer/"
genServicePath := projectPath + projectName + "service/"
genTestPath := projectPath + projectName + "test/"
genTypesPath := projectPath + projectName + "types/"
genModsPath := projectPath + projectName + "go.mod"
genPaths := []string{genApiPath, genCmdPath, genConfigPath, genConstsPath, genLoadingPath, genMiddlewarePath, genPkgPath, genRepositoryPath, genRouterPath, genSerializerPath, genServicePath, genTestPath, genTypesPath, genModsPath}} 1.3 config 配置文件生成
我们逐个遍历上面的数组列表,会针对一些特定特殊的 path 进行操作。比如这个config,我们会生成对应的config.yaml 配置文件
case genConfigPath:if err := gfile.Mkdir(genConfigPath); err != nil {
glog.Fatal("mkdir for generating path:%s failed: %v", genPath, err)}if err := gfile.Mkdir(genConfigPath + "local/"); err != nil {
glog.Fatal("mkdir for generating path:%s failed: %v", genPath, err)}
yamlPath := genConfigPath + "local/config.yaml"
entityContent := gstr.ReplaceByMap(configYamlTemplate, g.MapStrStr{"{domain}": projectName[:len(projectName)-1],})if err := writeFile(yamlPath, entityContent); err != nil {return err }
entityContent = strings.Replace(configGolangTemplate, "'", "`", -1)
configGo := genConfigPath + "config.go"if err := writeFile(configGo, entityContent); err != nil {return err } 以下就是yaml文件的生成代码文件模版,如果需要什么再往上面加就好了。
const configYamlTemplate = `
system:
domain: {domain}
version: 1.0
appEnv: "test"
HttpPort: ":4000"
Host: "localhost"
mysql:
default:
dialect: "mysql"
host: "127.0.0.1"
port: "3306"
dbName: "hello_story"
user: "root"
password: "root"
charset: "utf8mb4"
redis:
name: 1
address: 127.0.0.1:6379
password:
` {domain}可以使用以下方法,对模版内容进行填充。
entityContent := gstr.ReplaceByMap(configYamlTemplate, g.MapStrStr{"{domain}": projectName[:len(projectName)-1],}) 1.4 生成go mod文件
由于go mod 文件的特殊性,我们要先获取系统的go版本。
func getGolangVersion() (string, error) {
ver := runtime.Version()if ver != "" {return ver[2:6], nil}return "", errors.New("golang 环境不存在")} go mod tidy1.5 脚本执行
由于引入了第三方包,所以我们最终还是要 go mod tidy 一下。
先测试网络环境
pingCmd := exec.Command("ping", "-c 5 baidu.com")_, err := pingCmd.CombinedOutput()if err != nil {
fmt.Println("err", err)return err} start.shcd {path}go env -w GOPROXY=,direct
go mod tidy go mod tidy下一步的话呢,打算把 model 也放进来,打通一下 model 层面的自动生成,curd的代码。