golang gin 项目中添加多个 cmd 命令行工具,如何进行目录组织

文章目录

    需求

    之前开发的大赛报名网站终于进入了收尾阶段,比赛已结束,现在需要把参赛选手上传的资料及视频文件导出,做备份。

    正好借此机会了解一下如何在 golang gin 项目中添加一堆命令行工具。

    为何要引入 cmd 目录

    之前把导出数据的功能,都放到了 gin API 接口中,然后通过 swagger 的文档管理界面调用,再保存。

    但是,这样搞有个坏处,就是导致 swagger 文档中,会多出很多不需要前端使用的接口。
    此外,像视频批量导出这样需要长时间执行的功能,需要更多详情日志的场景,也不适合放到 API 接口中。

    所以,我需要将这些功能从 HTTP API 接口中剥离出来,放到单独的命令行工具中。然后代码目录组织就变成了一个问题 🤔

    golang gin 中 cmd 命令的目录结构

    印象中 Golang 官方是有目录结构组织的推荐结构的。

    cmd/ 目录区分

    在项目根目录下建立 cmd 文件夹,其中包含多个子目录,每个子目录是一个独立的命令(如 cmd/format-tool, cmd/cli-tool),每个子目录都有自己的 main.go 文件。

    例如:

    my-gin-app/
    ├── cmd/          // 存放多个入口命令
    │   ├── tool1/
    │   │   └── main.go
    │   ├── tool2/
    │   │   └── main.go
    │   └── tool3/
    │       └── main.go
    ├── go.mod
    ├── go.sum
    └── main.go
    

    这样,我只需要在当前的 gin 项目目录中新建一个 cmd/export 目录,在里面放一个 main.go 文件。

    mkdir -p cmd/export
    touch cmd/export/main.go
    

    我发现多年前,我就测试过多个 main 的情况:

    如何组织 Golang 项目目录,使一个项目包含多个 main 入口程序

    main.go 代码示例

    如何设置 package 呢?是否可以使用 main 作为 package 名称?因为原 gin 的入口文件 main.go 就是 main 作为包名。

    测试了一下确实可以的:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	fmt.Println("Hello world")
    }
    

    执行:

    > go run main.go
    Hello world
    

    然后,我又测试了一下原 gin 项目的编译,并不影响,很好。(๑•̀ㅂ•́)و✧

    如何引用 gin 中的 Model 代码

    跟其他包一样引用即可:

    package main
    
    import (
    	"fmt"
    
    	"sunzhongwei.com/my_project/models"
    )
    
    func main() {
    	fmt.Println("Hello world")
    
    	fmt.Println(models.Account{}.EditableFields())
    }
    

    不便的地方

    由于之前 gin 项目中把数据库初始化放到了 main.go 中,导致在 cmd 中想直接使用 db 很麻烦。。。
    还是把初始化逻辑放到 models 模块中比较合适。

    是否需要使用 Cobra

    对应简单的使用场景,不需要大量子命令的情况,我感觉可以不使用 Cobra。

    等 cmd 命令多了,重合度高了之后,再引入 Cobra 也不迟。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式