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

更新日期: 2025-09-01 阅读次数: 14 字数: 934 分类: golang

需求

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

正好借此机会了解一下如何在 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 聊聊, 查看更多联系方式