
go install 和 go build 本质区别在哪
根本不是“安装 vs 编译”这种字面理解——go install 和 go build 都会编译,关键差异在于:是否把结果二进制文件放到 $GOBIN(或 $GOPATH/bin),以及是否自动处理依赖的可执行包。
-
go build默认只在当前目录生成可执行文件,不移动、不安装,也不管你有没有在main包里引用其他命令行工具 -
go install会把编译结果复制到$GOBIN,并**强制重新编译所有被该命令依赖的、声明为package main的模块**(哪怕它们之前已编译过) - Go 1.16+ 后,
go install还支持直接安装远程模块(如go install github.com/xxx/cli@latest),而go build完全不支持这种用法
什么时候必须用 go install 而非 go build
当你写的程序要被其他 Go 命令或 shell 环境直接调用时,比如作为 go 的子命令(go-foo)、CI 脚本里的工具、或者想全局使用却不手动加 ./ 前缀。
- 开发 CLI 工具并希望用户运行
mytool --help而非./mytool --help→ 必须go install - 用
go run测试没问题,但go build出来的二进制一运行就报command not found: xxx→ 很可能它依赖的另一个main包没装上,得用go install一起拉 - 模块启用了
go.work或多模块 workspace →go install会按 workspace 规则解析依赖,go build只认当前模块根目录
GOBIN 和 GOPATH 下的 bin 目录容易混淆
go install 写入的目标路径优先级是:$GOBIN > $GOPATH/bin。如果两个都设了,只认 $GOBIN;如果都没设,默认用 $GOPATH/bin(而 $GOPATH 默认是 $HOME/go)。
- 执行
go install后找不到命令?先检查echo $GOBIN和echo $PATH是否包含对应路径 - Mac M1 用户常见坑:
go install生成的是 arm64 二进制,但 shell 是 rosetta 启动的 x86_64 环境 → 运行时报bad CPU type in executable -
go build -o /usr/local/bin/mycmd看似等价,但绕过了 Go 的模块缓存和依赖重编译逻辑,后续更新依赖时容易漏掉同步
Go 1.21+ 的变化:go install 不再隐式构建当前目录
旧版 Go(≤1.20)在项目根目录下执行 go install 会默认编译当前模块的 main 包;新版必须显式指定包路径,否则报错:go install: no arguments specified。
立即学习“go语言免费学习笔记(深入)”;
- 想装当前项目:用
go install ./cmd/myapp(假设入口在cmd/myapp) - 想装本地模块里的某个命令:不能只写
go install .,得写全go install ./...或具体路径 - 远程安装仍照旧:
go install golang.org/x/tools/cmd/gopls@latest不受影响
这个改动让行为更明确,但也让脚本迁移时容易卡住——尤其以前靠 go install 自动发现 main 包的 Makefile 或 CI 步骤,现在得补上路径。









