Go交叉编译必须显式设置GOOS和GOARCH环境变量,缺一不可;通常还需CGO_ENABLED=0以实现静态链接,避免libc依赖问题;go run不支持跨平台,仅用于本地调试。

go build 交叉编译必须显式设 GOOS 和 GOARCH
Go 原生支持跨平台构建,但 go build 不会自动猜目标系统——不设环境变量就永远只生成当前平台的二进制。
-
GOOS=linux GOARCH=arm64 go build -o mytool .→ Linux ARM64 可执行文件 -
GOOS=windows GOARCH=386 go build -o mytool.exe .→ Windows 32 位 exe -
GOOS=darwin GOARCH=amd64 go build -o mytool .→ macOS Intel 版本
常见组合可查 go tool dist list,注意 GOARCH 对于 macOS 是 amd64 或 arm64(不是 x86_64),Windows 下是 386 或 amd64(不是 x64)。
CGO_ENABLED=0 是静态链接的关键开关
默认开启 CGO 时,go build 会链接系统 C 库(如 glibc),导致 Linux 二进制在 Alpine 或旧版系统上直接报 not found 错误;macOS/Windows 虽不依赖 glibc,但启用 CGO 仍可能引入非标准依赖。
- 加
CGO_ENABLED=0强制纯 Go 静态链接:CGO_ENABLED=0 GOOS=linux go build -o mytool . - 若代码里用了
cgo(比如调用 SQLite、OpenSSL),则不能关;此时需用对应平台的交叉编译工具链或 Docker 构建 - Windows 上即使不开 CGO,
.exe也天然静态,无需额外处理
Makefile 封装多平台构建更可靠
手动敲一堆 GOOS=xxx GOARCH=yyy 容易漏、难复现;用 Makefile 固化命令,还能统一加 -mod=vendor 或 -ldflags。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 定义变量:
GOOS ?= linux允许外部覆盖,GOARCH ?= amd64 - 导出环境变量:
export GOOS GOARCH,否则子 shell 读不到 - 典型目标:
make build-linux-amd64、make build-windows,内部调用go build -o bin/mytool-$(GOOS)-$(GOARCH)
别忘了加 .PHONY 声明这些是伪目标,否则 Make 可能误判文件名冲突。
go run 不能跨平台,仅限本地调试
go run 是编译+运行一体,它永远用宿主机环境执行,不接受 GOOS/GOARCH,也不生成目标平台二进制——想验证 Windows 行为?必须真机或用 GOOS=windows go build 后扔到 Windows 上跑。
-
go run .:只运行当前目录下所有package main文件,不处理子目录(如cmd/mytool) -
go run ./cmd/mytool:可指定路径,但依然只在当前系统执行 - 调试阶段可用
go run -gcflags="all=-N -l"关闭优化,方便 Delve 断点;发布前务必切回go build
真正交付的 CLI 工具,最终一定得靠 go build 输出独立二进制——go run 留给开发过程,别混进 CI 或发布流程。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










