Go mod 好菜系列 - 0x06 cobra 把命令行项目做得像样一点
详细讲 cobra 能做什么、为什么 Go CLI 项目常用它、命令树/flags/执行入口如何组织,以及它在工程里的位置。
如果你写的 Go 项目不只是一个 HTTP 服务,而是还带一些管理命令、运维脚本、导入导出工具,甚至本身就是 CLI 应用,那么你很快就会碰到 cobra。它不是每个项目都必需,但一旦项目开始有命令树,它就会变得很顺手。
cobra 是干嘛的
一句话:它是一个命令行应用框架。你可以用它来组织:
- 主命令
- 子命令
- flags
- 帮助文档
- 初始化流程
也就是说,它帮你把一个“会跑的命令行程序”整理成“结构清楚的命令行项目”。
为什么 cobra 常见
因为 Go 生态里很多工具本身就是 CLI,比如:
- 运维辅助工具
- 代码生成器
- 管理后台命令
- 迁移工具
- Kubernetes 相关工具
而 cobra 在这条线上几乎是个“默认会考虑”的选手。
最基础的命令长什么样
var rootCmd = &cobra.Command{
Use: "app",
Short: "A simple CLI app",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("hello cobra")
},
}
func main() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}这里的关键其实是那颗命令树。rootCmd 是根命令,后面你可以不断给它挂子命令。
子命令才是 cobra 真正的味道
var migrateCmd = &cobra.Command{
Use: "migrate",
Short: "run db migrations",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("migrating...")
},
}
func init() {
rootCmd.AddCommand(migrateCmd)
}这时候你就能跑:
app migrate如果项目里有启动服务、建表、导入数据、生成文件这些动作,cobra 会很好组织。
flags 是 CLI 的日常刚需
var port int
func init() {
rootCmd.Flags().IntVar(&port, "port", 8080, "server port")
}然后执行:
app --port 9090你会发现,flags、帮助信息、命令说明,这些本来很零碎的东西,cobra 都给你整理好了。
它通常和 viper 一起出现
这个搭配非常常见。原因也简单:
- cobra 负责命令结构
- viper 负责配置读取
命令行参数、配置文件、环境变量三者一打通,一个 CLI 工具或管理程序的骨架就很完整了。
cobra 最适合放在哪
如果项目有 CLI 层,cobra 就应该待在入口和命令组织那层。别把业务全塞进每个命令定义里,命令函数仍然应该更多负责“调度”,而不是把所有细节都写成一个超长 Run。
什么时候没必要用 cobra
如果你的程序只有一个很简单的入口,甚至没有子命令,没有复杂 flags,也不打算发展成 CLI 工具,那直接用标准库的 flag 包都完全可以。不是所有命令行程序都值得上框架。
小结
cobra 这道菜不是天天吃,但在它出现的场景里通常很顶用:
- 它擅长组织命令树、flags 和帮助信息
- 特别适合管理命令、脚手架和 CLI 工具
- 常和 viper 组合成入口层基础设施
- 简单程序别为了看起来正规而强上
这一套 Go mod 好菜系列 到这里先告一段落。后面如果继续扩,我会优先考虑再补 validator、jwt、sqlx、ent 这些更贴近常规项目的模块。