选cobra而非手写flag因其天然支持子命令、自动帮助生成、参数补全和嵌套路由,避免手动解析args、help同步错乱及flag冲突等问题。

为什么选 cobra 而不是手写 flag
因为 cobra 天然支持子命令、自动帮助生成、参数补全和命令嵌套,而纯 flag 在实现 todo add "buy milk"、todo list --done、todo done 5 这类交互时,很快会陷入手动解析、重复校验、help 文案同步错乱的泥潭。
常见错误现象:flag.Parse() 后还要自己切 os.Args 判断子命令;忘记处理 --help 时 panic;不同命令间共享 flag 导致冲突。
- 用
cobra就不用管os.Args[0]是什么,它自动路由到对应Cmd -
cobra的Args: cobra.ExactArgs(1)比手写len(args) != 1更语义化且带默认报错 - 所有 help、usage、error 输出格式统一,改一个地方全局生效
cobra init 后必须立刻改的三处
执行 cobra init todo 生成的模板看着干净,但直接跑会出问题:命令没持久化、配置路径硬编码、rootCmd 没设 UsageFunc。
使用场景:你希望 todo list 显示最近添加的条目,而不是空列表或 panic。
立即学习“go语言免费学习笔记(深入)”;
- 删掉
cmd/root.go里默认的fmt.Println("not implemented"),换成实际逻辑入口(比如调loadTodos()) - 把
configFile变量改成用户主目录下的.todo.json:filepath.Join(os.Getenv("HOME"), ".todo.json") - 在
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")下加一行:rootCmd.SetUsageFunc(customUsageFunc),否则子命令 help 会漏掉父级 flag
todo add 命令里怎么安全处理用户输入
用户输 todo add 不带内容,或内容全是空格,或含换行符——这些都会让 JSON 存储失败或显示异常。
性能影响:每次 add 都要读+写整个文件,但对百条以内的 TODO 列表,比引入 bolt/badger 更轻量也更易调试。
- 用
cobra.MinimumNArgs(1)替代ExactArgs(1),允许todo add "a" "b" "c"批量添加 - 对每个参数做
strings.TrimSpace(),再判空;空字符串直接跳过,不存也不报错 - 存之前用
json.MarshalIndent(),别用json.Marshal()—— 方便人眼查.todo.json文件时 debug - 写文件前先
ioutil.WriteFile(tmpPath, data, 0644),成功后再os.Rename(),避免写到一半崩溃导致数据丢失
Windows 下 todo 命令找不到可执行文件?
Go 编译默认输出 todo.exe,但 cobra 生成的 root.go 里 Use: "todo" 没带 .exe 后缀,导致 todo list 在 cmd 中提示“不是内部或外部命令”。
兼容性影响:Linux/macOS 用户不会遇到,但 Windows 用户第一次构建后常卡在这步。
- 编译时加
-o todo.exe(推荐),而不是依赖默认名 - 或者改
rootCmd.Use为filepath.Base(os.Args[0]),让它自动适配当前二进制名 - 检查
PATH是否包含你的构建目录;临时测试可直接运行./todo.exe list
容易被忽略的是:Cobra 默认把 Use 当作命令名展示,但 Windows 对可执行文件后缀敏感,这个细节不调通,整个 CLI 就没法用。










