如何通过单条 go get 命令同时安装 Go 项目中的库与可执行文件

在 go 中,可通过 `go get github.com/your/repo/...`(含三点省略号)一次性下载并安装仓库中所有子目录下的可执行程序(含 `main` 包)及依赖库,无需为每个二进制单独执行 `go get`。

Go 的模块构建与安装机制默认按“包”(package)粒度工作:只有包含 package main 且至少一个源文件定义了 func main() 的目录,才会被 go install(或 go get 在较新版本中等效行为)编译为可执行文件。而普通库包(如 config/、crypto/)则仅被下载和缓存,供其他项目导入使用。

回到你的项目结构:

github.com/myproject/demo/
├── config/
├── crypto/
├── demo/          // ← 含 executable.go 和 package main
├── deps.go
├── LICENSE
├── README.md
└── demo.go        // ← 可能是库入口,package demo

当前你需运行 go get github.com/myproject/demo/demo 才能安装二进制,是因为 go get 默认只处理指定路径的单个包。但 Go 支持通配符式递归匹配——使用 ...(三点省略号)可匹配当前路径下所有子目录及其嵌套子目录中的合法 Go 包。

✅ 正确做法是:

go get github.com/myproject/demo/...

该命令将:

  • 遍历 demo/ 下所有子目录(包括 demo/ 自身、config/、crypto/、以及未来新增的 cmd/xxx/ 等);
  • 对每个含 package main 的目录,自动执行 go install,生成对应二进制(如 demo)并放入 $GOBIN(默认为 $GOPATH/bin 或 go env GOPATH 下的 bin 目录);
  • 同时下载并缓存所有库包(如 config、crypto),供本地或他人项目 import 使用。

⚠️ 注意事项:

  • ... 不匹配隐藏目录(以 . 开头,如 .github/)或 vendor/(若启用 module 模式则通常忽略);
  • Go 1.16+ 默认启用 GO111MODULE=on,确保你在模块根目录(含 go.mod)下操作;若尚未初始化模块,请先运行 go mod init github.com/myproject/demo;
  • 若 demo/ 目录下存在多个 main 包(例如 demo/cmd/api/ 和 demo/cmd/cli/),... 会一并安装全部二进制,命名依据其目录名(如 api、cli);
  • go get 在 Go 1.17+ 中已主要作为依赖管理命令,安装二进制推荐显式使用 go install(如 go install github.com/myproject/demo/demo@latest),但 go get repo/... 仍向后兼容并有效。

? 最佳实践建议:将所有可执行文件统一置于 cmd/ 子目录下(如 cmd/demo/),既符合 Go 社区惯例,也便于权限隔离与版本控制。此时只需 go get github.com/myproject/demo/cmd/... 即可精准安装全部工具,避免误装非命令类 main 包。

总结:用 ... 是标准、简洁且可靠的方式,一条命令完成库与二进制的同步获取与安装,无需额外脚本或构建逻辑。