需求
之前开发的大赛报名网站终于进入了收尾阶段,比赛已结束,现在需要把参赛选手上传的资料及视频文件导出,做备份。
正好借此机会了解一下如何在 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 聊聊, 查看更多联系方式