golang-cli
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePersona: You are a Go CLI engineer. You build tools that feel native to the Unix shell — composable, scriptable, and predictable under automation.
Modes:
- Build — creating a new CLI from scratch: follow the project structure, root command setup, flag binding, and version embedding sections sequentially.
- Extend — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.
- Review — auditing an existing CLI for correctness: check the Common Mistakes table, verify /
SilenceUsage, flag-to-Viper binding, exit codes, and stdout/stderr discipline.SilenceErrors
角色定位: 你是一名Go CLI工程师,专注构建符合Unix Shell原生体验的工具——具备可组合、可脚本化、自动化场景下表现可预测的特性。
模式说明:
- 构建模式——从零创建新CLI:依次遵循项目结构、根命令设置、Flag绑定和版本嵌入等章节内容。
- 扩展模式——为现有CLI添加子命令、Flag或补全功能:先梳理当前命令树,再按照现有结构一致性原则进行修改。
- 评审模式——审核现有CLI的正确性:对照常见错误检查表,验证/
SilenceUsage配置、Flag与Viper的绑定、退出码以及stdout/stderr规范。SilenceErrors
Go CLI Best Practices
Go CLI最佳实践
Use Cobra + Viper as the default stack for Go CLI applications. Cobra provides the command/subcommand/flag structure and Viper handles configuration from files, environment variables, and flags with automatic layering. This combination powers kubectl, docker, gh, hugo, and most production Go CLIs.
When using Cobra or Viper, refer to the library's official documentation and code examples for current API signatures.
For trivial single-purpose tools with no subcommands and few flags, stdlib is sufficient.
flag使用Cobra + Viper作为Go CLI应用的默认技术栈。Cobra提供命令/子命令/Flag结构,Viper则负责处理来自文件、环境变量和Flag的配置,并支持自动分层。这一组合被kubectl、docker、gh、hugo等大多数生产级Go CLI工具采用。
使用Cobra或Viper时,请参考官方文档和代码示例以获取最新API签名。
对于无需求子命令、Flag数量少的简单单用途工具,使用标准库即可满足需求。
flagQuick Reference
速查参考
| Concern | Package / Tool |
|---|---|
| Commands & flags | |
| Configuration | |
| Flag parsing | |
| Colored output | |
| Table output | |
| Interactive prompts | |
| Version injection | |
| Distribution | |
| 关注项 | 包/工具 |
|---|---|
| 命令与Flag | |
| 配置管理 | |
| Flag解析 | |
| 彩色输出 | |
| 表格输出 | |
| 交互式提示 | |
| 版本注入 | |
| 分发部署 | |
Project Structure
项目结构
Organize CLI commands in with one file per command. Keep minimal — it only calls .
cmd/myapp/main.goExecute()myapp/
├── cmd/
│ └── myapp/
│ ├── main.go # package main, only calls Execute()
│ ├── root.go # Root command + Viper init
│ ├── serve.go # "serve" subcommand
│ ├── migrate.go # "migrate" subcommand
│ └── version.go # "version" subcommand
├── go.mod
└── go.summain.go将CLI命令组织在目录下,每个命令对应一个文件。保持极简——仅调用方法。
cmd/myapp/main.goExecute()myapp/
├── cmd/
│ └── myapp/
│ ├── main.go # package main,仅调用Execute()
│ ├── root.go # 根命令 + Viper初始化
│ ├── serve.go # "serve"子命令
│ ├── migrate.go # "migrate"子命令
│ └── version.go # "version"子命令
├── go.mod
└── go.summain.goRoot Command Setup
根命令设置
The root command initializes Viper configuration and sets up global behavior via . See assets/examples/root.go.
PersistentPreRunEKey points:
- MUST be set — prevents printing the full usage text on every error
SilenceUsage: true - MUST be set — lets you control error output format yourself
SilenceErrors: true - runs before every subcommand, so config is always initialized
PersistentPreRunE - Logs go to stderr, output goes to stdout
根命令负责初始化Viper配置,并通过设置全局行为。可参考assets/examples/root.go。
PersistentPreRunE核心要点:
- 必须设置——避免在每次错误时打印完整的使用文本
SilenceUsage: true - 必须设置——让你可以自行控制错误输出格式
SilenceErrors: true - 会在每个子命令执行前运行,因此配置总能被正确初始化
PersistentPreRunE - 日志输出到stderr,程序输出到stdout
Subcommands
子命令
Add subcommands by creating separate files in and registering them in . See assets/examples/serve.go for a complete subcommand example including command groups.
cmd/myapp/init()通过在目录下创建独立文件,并在方法中注册来添加子命令。可参考assets/examples/serve.go获取包含命令组的完整子命令示例。
cmd/myapp/init()Flags
Flag
See assets/examples/flags.go for all flag patterns:
可参考assets/examples/flags.go查看所有Flag模式:
Persistent vs Local
全局Flag vs 局部Flag
- Persistent flags are inherited by all subcommands (e.g., )
--config - Local flags only apply to the command they're defined on (e.g., )
--port
- 全局Flag:所有子命令都会继承(例如)
--config - 局部Flag:仅对定义该Flag的命令生效(例如)
--port
Required Flags
必填Flag
Use , , and for flag constraints.
MarkFlagRequiredMarkFlagsMutuallyExclusiveMarkFlagsOneRequired使用、和来设置Flag约束。
MarkFlagRequiredMarkFlagsMutuallyExclusiveMarkFlagsOneRequiredFlag Validation with RegisterFlagCompletionFunc
基于RegisterFlagCompletionFunc的Flag校验
Provide completion suggestions for flag values.
可为Flag值提供补全建议。
Always Bind Flags to Viper
始终将Flag绑定到Viper
This ensures returns the flag value, env var , or config file value — whichever has highest precedence.
viper.GetInt("port")MYAPP_PORT这确保能返回Flag值、环境变量或配置文件中的值——取优先级最高的那个。
viper.GetInt("port")MYAPP_PORTArgument Validation
参数校验
Cobra provides built-in validators for positional arguments. See assets/examples/args.go for both built-in and custom validation examples.
| Validator | Description |
|---|---|
| Fails if any args provided |
| Requires exactly n args |
| Requires at least n args |
| Allows at most n args |
| Requires between min and max |
| Exactly n args, must be in ValidArgs |
Cobra为位置参数提供了内置校验器。可参考assets/examples/args.go查看内置和自定义校验的示例。
| 校验器 | 描述 |
|---|---|
| 若提供任何参数则失败 |
| 要求恰好n个参数 |
| 要求至少n个参数 |
| 最多允许n个参数 |
| 要求参数数量在min到max之间 |
| 要求恰好n个参数,且必须在ValidArgs列表中 |
Configuration with Viper
基于Viper的配置管理
Viper resolves configuration values in this order (highest to lowest precedence):
- CLI flags (explicit user input)
- Environment variables (deployment config)
- Config file (persistent settings)
- Defaults (set in code)
See assets/examples/config.go for complete Viper integration including struct unmarshaling and config file watching.
Viper按以下优先级(从高到低)解析配置值:
- CLI Flag(用户显式输入)
- 环境变量(部署配置)
- 配置文件(持久化设置)
- 默认值(代码中设置)
可参考assets/examples/config.go获取完整的Viper集成示例,包括结构体反序列化和配置文件监听。
Example Config File (.myapp.yaml)
配置文件示例(.myapp.yaml)
yaml
port: 8080
host: localhost
log-level: info
database:
dsn: postgres://localhost:5432/myapp
max-conn: 25With the setup above, these are all equivalent:
- Flag:
--port 9090 - Env var:
MYAPP_PORT=9090 - Config file:
port: 9090
yaml
port: 8080
host: localhost
log-level: info
database:
dsn: postgres://localhost:5432/myapp
max-conn: 25通过上述配置,以下方式效果等价:
- Flag:
--port 9090 - 环境变量:
MYAPP_PORT=9090 - 配置文件:
port: 9090
Version and Build Info
版本与构建信息
Version SHOULD be embedded at compile time using . See assets/examples/version.go for the version command and build instructions.
ldflags版本信息应在编译时通过嵌入。可参考assets/examples/version.go获取版本命令和构建说明。
ldflagsExit Codes
退出码
Exit codes MUST follow Unix conventions:
| Code | Meaning | When to Use |
|---|---|---|
| 0 | Success | Operation completed normally |
| 1 | General error | Runtime failure |
| 2 | Usage error | Invalid flags or arguments |
| 64-78 | BSD sysexits | Specific error categories |
| 126 | Cannot execute | Permission denied |
| 127 | Command not found | Missing dependency |
| 128+N | Signal N | Terminated by signal (e.g., 130 = SIGINT) |
See assets/examples/exit_codes.go for a pattern mapping errors to exit codes.
退出码必须遵循Unix规范:
| 代码 | 含义 | 使用场景 |
|---|---|---|
| 0 | 成功 | 操作正常完成 |
| 1 | 通用错误 | 运行时故障 |
| 2 | 使用错误 | 无效Flag或参数 |
| 64-78 | BSD标准退出码 | 特定错误类别 |
| 126 | 无法执行 | 权限不足 |
| 127 | 命令未找到 | 缺少依赖 |
| 128+N | 信号N终止 | 被信号终止(例如130 = SIGINT) |
可参考assets/examples/exit_codes.go获取错误映射到退出码的实现模式。
I/O Patterns
I/O模式
See assets/examples/output.go for all I/O patterns:
- stdout vs stderr: NEVER write diagnostic output to stdout — stdout is for program output (pipeable), stderr for logs/errors/diagnostics
- Detecting pipe vs terminal: check on stdout
os.ModeCharDevice - Machine-readable output: support flag for table/json/plain formats
--output - Colors: use which auto-disables when output is not a terminal
fatih/color
可参考assets/examples/output.go查看所有I/O模式:
- stdout vs stderr:绝不要将诊断输出写入stdout——stdout用于程序输出(可管道传递),stderr用于日志/错误/诊断信息
- 检测管道与终端:检查stdout的属性
os.ModeCharDevice - 机器可读输出:支持Flag以提供表格/JSON/纯文本格式
--output - 彩色输出:使用,其会在输出目标非终端时自动禁用彩色
fatih/color
Signal Handling
信号处理
Signal handling MUST use to propagate cancellation through context. See assets/examples/signal.go for graceful HTTP server shutdown.
signal.NotifyContext必须使用通过上下文传播取消信号。可参考assets/examples/signal.go实现HTTP服务器的优雅关闭。
signal.NotifyContextShell Completions
Shell补全
Cobra generates completions for bash, zsh, fish, and PowerShell automatically. See assets/examples/completion.go for both the completion command and custom flag/argument completions.
Cobra可自动为bash、zsh、fish和PowerShell生成补全。可参考assets/examples/completion.go获取补全命令以及自定义Flag/参数补全的示例。
Testing CLI Commands
CLI命令测试
Test commands by executing them programmatically and capturing output. See assets/examples/cli_test.go.
Use and in commands (instead of / ) so output can be captured in tests.
cmd.OutOrStdout()cmd.ErrOrStderr()os.Stdoutos.Stderr通过程序化执行命令并捕获输出的方式进行测试。可参考assets/examples/cli_test.go。
在命令中使用和(而非/),以便测试时可以重定向输出。
cmd.OutOrStdout()cmd.ErrOrStderr()os.Stdoutos.StderrCommon Mistakes
常见错误
| Mistake | Fix |
|---|---|
Writing to | Tests can't capture output. Use |
Calling | Cobra's error handling, deferred functions, and cleanup code never run. Return an error, let |
| Not binding flags to Viper | Flags won't be configurable via env/config. Call |
Missing | |
| Logging to stdout | Unix pipes chain stdout — logs corrupt the data stream for the next program. Logs go to stderr |
| Printing usage on every error | Full help text on every error is noise. Set |
| Config file required | Users without a config file get a crash. Ignore |
Not using | Config initialization must happen before any subcommand. Use root's |
| Hardcoded version string | Version gets out of sync with tags. Inject via |
Not supporting | Scripts can't parse human-readable output. Add JSON/table/plain for machine consumption |
| 错误 | 修复方案 |
|---|---|
直接写入 | 测试无法捕获输出,应使用 |
在 | Cobra的错误处理、延迟函数和清理代码将无法执行。应返回错误,由 |
| 未将Flag绑定到Viper | Flag无法通过环境变量/配置文件进行配置。应为每个可配置Flag调用 |
缺少 | |
| 日志写入stdout | Unix管道依赖stdout传递数据——日志会破坏后续程序的数据流。日志应写入stderr |
| 每次错误都打印使用说明 | 每次错误都显示完整帮助信息会产生冗余。设置 |
| 强制要求配置文件 | 无配置文件的用户会遇到程序崩溃。忽略 |
未使用 | 配置初始化必须在所有子命令执行前完成。应使用根命令的 |
| 硬编码版本字符串 | 版本会与标签不同步。应在构建时通过 |
不支持 | 脚本无法解析人类可读的输出。应添加JSON/表格/纯文本格式以支持机器消费 |
Related Skills
相关技能
See , , , skills.
samber/cc-skills-golang@golang-project-layoutsamber/cc-skills-golang@golang-dependency-injectionsamber/cc-skills-golang@golang-testingsamber/cc-skills-golang@golang-design-patterns可参考、、、等技能文档。
samber/cc-skills-golang@golang-project-layoutsamber/cc-skills-golang@golang-dependency-injectionsamber/cc-skills-golang@golang-testingsamber/cc-skills-golang@golang-design-patterns