Go 语言编译为 Windows、macOS、Linux 的正确方法
Go 的跨平台编译非常方便,但真正发布软件时,不能只记住 GOOS 和 GOARCH。你还要考虑 CGO、动态库、CPU 架构、文件路径、证书和 CI 构建环境。
这篇文章整理一套更稳的构建方法。
一、最基本的交叉编译
Go 通过 GOOS 和 GOARCH 指定目标平台。
构建 Linux:
1 | GOOS=linux GOARCH=amd64 go build -o dist/myapp-linux-amd64 ./cmd/server |
构建 Windows:
1 | GOOS=windows GOARCH=amd64 go build -o dist/myapp-windows-amd64.exe ./cmd/server |
构建 macOS:
1 | GOOS=darwin GOARCH=arm64 go build -o dist/myapp-darwin-arm64 ./cmd/server |
Windows 可执行文件通常要带 .exe 后缀。
二、常见 GOOS 和 GOARCH
常用系统:
1 | GOOS=linux |
常用架构:
1 | GOARCH=amd64 |
现在服务器和桌面环境里,amd64 和 arm64 都很常见。不要只发一个架构版本。
三、CGO 会让交叉编译变复杂
纯 Go 项目交叉编译最轻松。如果项目使用了 CGO,例如依赖 SQLite C 库、系统 OpenSSL、某些图像处理库,跨平台编译会明显复杂。
可以先尝试关闭 CGO:
1 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/myapp ./cmd/server |
但如果依赖必须使用 CGO,就不要硬凑命令。更稳的方式是在目标平台原生构建,或者用 CI matrix 分别在 Linux、Windows、macOS 上构建。
四、减少二进制体积
发布命令行工具或服务端程序时,可以去掉部分调试符号:
1 | go build -ldflags="-s -w" -o dist/myapp ./cmd/server |
这会减小体积,但调试信息也会减少。线上排查困难的项目,可以保留一份未裁剪版本。
五、写入版本信息
发布软件时,最好把版本号、Git commit、构建时间写进二进制:
1 | go build \ |
代码里定义变量:
1 | var version = "dev" |
这样线上执行 myapp version 时,就能知道当前运行的是哪一版。
六、macOS 要区分 Intel 和 Apple Silicon
macOS 至少要考虑两个架构:
1 | GOOS=darwin GOARCH=amd64 go build -o dist/myapp-darwin-amd64 ./cmd/server |
如果面向普通用户分发,还会涉及签名、公证和 Gatekeeper。那是发布流程问题,不只是 Go 编译问题。
七、推荐使用 CI 构建
最稳的方式是让 CI 在不同平台上构建:
1 | strategy: |
纯 Go 项目可以本机交叉编译。有 CGO 或系统依赖时,CI 原生构建会省很多麻烦。
八、实践建议
Go 跨平台编译的正确姿势是:纯 Go 项目用 GOOS、GOARCH 快速构建,有 CGO 的项目让目标平台自己构建。
发布前至少在目标系统上启动一次,检查配置路径、日志路径、证书访问、权限和命令行参数。跨平台不是只改环境变量,真正可靠要靠构建和验证流程一起兜住。