最近在做毕设,前台做完了,现在要开始搭建后台系统了,而后台系统,又大多数是固定的模版。
所以为了方便摸鱼,顺便写一个可以 自动生成模版 的代码工具
开源地址: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 tidy
1.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.sh
cd {path}go env -w GOPROXY=,direct go mod tidy
go mod tidy
下一步的话呢,打算把 model 也放进来,打通一下 model 层面的自动生成,curd的代码。