写 Go 命令行小工具时我常用的几个习惯

平时会写一些内部用的命令行小工具,Go 是我最常用的语言:编译出来就是一个可执行文件,丢到服务器上就能跑。工具写多了,慢慢形成了几个固定的习惯,整理出来分享一下。

1. main 只负责组装,逻辑放进 run

main 函数里不写业务逻辑,只做参数解析和退出码处理,真正的逻辑放进一个返回 error 的 run 函数。这样既方便写单元测试,也不会到处散落 os.Exit。

go 复制代码
func main() {
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()
	if err := run(ctx, os.Args[1:]); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

2. 用 context 统一处理退出信号

上面的 signal.NotifyContext 会在收到 Ctrl+C 时取消 ctx。只要下游的 HTTP 请求、数据库查询都接收这个 ctx,按下 Ctrl+C 后工具就能干净地退出,不会留下写了一半的文件。

3. 给慢操作加超时

调用外部接口时,单独包一层超时,避免网络抖动时工具一直卡住:

go 复制代码
reqCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(reqCtx, http.MethodGet, url, nil)

4. 错误信息写给使用者看

返回错误时带上"在做什么"和关键参数,比如 fmt.Errorf("读取配置 %s 失败: %w", path, err)。用工具的人往往不看源码,一条清楚的错误信息能省掉很多来回沟通。

5. 分清 stdout 和 stderr

结果输出到 stdout,进度和日志输出到 stderr。这样别人可以放心地把结果用管道交给 jq 或 grep 处理,不会被日志混进去。

小结

这些习惯都不复杂,但坚持下来之后,工具的可维护性和使用体验都会好很多。如果你也有类似的小经验,欢迎一起交流。

相关推荐
我的div丢了肿么办9 天前
gin框架设置/获取cookie和多个二级域名共享cookie
后端·google
GlobalTradercrb16 天前
独立站SEO先写博客还是先优化产品页?看站点阶段
数据库·人工智能·google·pdf·go·seo
智码看视界16 天前
开源大模型追踪:TurboQuant量化指南:128K上下文不再爆显存,KV缓存3-bit免重训
google·开源大模型·llama.cpp·显存优化·长上下文推理·turboquant·本地部署 开源大模型
Frag0ut20 天前
获取Chrome官方安装包:离线版安装风险避坑指南
chrome·google·谷歌浏览器·安装包·chromesetup.exe·在线安装包·离线版
知之则吱吱23 天前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
Frag0ut25 天前
Chrome数据备份指南:本地备份还原书签密码与扩展配置工具
chrome·google·谷歌浏览器·数据同步·备份工具·配置迁移·书签密码备份
GlobalAIagent25 天前
外贸站上线前的技术自查清单:漏一项询盘可能消失
google·typescript·ar·go语言·seo
知昂七昂25 天前
00-01:AOSP 源码仓库结构与 repo 工作流源码剖析(Android 16 / aosp-main)
android·google
Frag0ut1 个月前
Chrome安全隐私设置指南:5个原生功能筑牢浏览器数字防线
chrome·google·谷歌浏览器·权限管理·隐私保护·安全设置·安全浏览