目录

Go 实现交叉编译,编译跨平台多端可执行文件

背景

之前给客户交付 Go 开发的工具时,对方既有 Windows 服务器又有 Linux 工作站,总不能在不同系统上重复编译。

后来发现 Go 原生支持的交叉编译简直是神器,上手后彻底解决了跨平台交付的麻烦。

相当于你可以在 windows 上开发,然后编译成 linux 可执行文件,上传到 linux 服务器上直接可执行(无需装 go 环境)

什么是交叉编译?

交叉编译简单说就是“在 A 系统上编译出能在 B 系统上运行的程序”,比如在 Windows 上编译出 Linux 可执行文件。

这在其他语言里并不容易——C++ 要装对应系统的编译链,Python 要确保目标系统有相同版本的解释器,而 GO 从 1.5 版本开始就内置了跨平台编译能力,核心原因是:

  • 编译时静态链接:GO 编译会把依赖的库都打包进可执行文件,目标系统不用装额外依赖,拿过去就能跑。

  • 内置多平台支持:GO 源码里自带了主流系统(Windows、Mac、Linux)和架构(32 位、64 位、ARM)的编译配置,不用手动适配。

在开始操作前,先确认 GO 版本(建议 1.16+,版本越新对新系统的支持越好),终端输入 go version 即可查看,

比如 go version go1.22.0 darwin/amd64 就表示是 Mac 64 位系统的 1.22.0 版本。

实现

Go的交叉编译核心是通过GOOSGOARCH两个环境变量指定目标平台,编译时工具链会根据这两个变量生成对应平台的二进制文件。

  • GOOS:指定目标操作系统,比如windows、linux、darwin(对应 macOS)、freebsd 等

  • GOARCH:指定目标CPU架构,比如amd64(64位)、386(32位)、arm64、mips等

这里分享几个开发中最常用的组合(覆盖90%以上场景):

目标平台 GOOS GOARCH 可执行文件后缀
Windows 64位 windows amd64 .exe
Linux 64位 linux amd64 无后缀
macOS 64位(Intel) darwin amd64 无后缀
macOS 64位(M1/M2) darwin arm64 无后缀
Linux ARM64(树莓派4等) linux arm64 无后缀

实操

mac、linux 环境下交叉编译为 windows 环境可执行文件 exe:

# 编译Windows 64位程序(Mac、linux环境下)
GOOS=windows GOARCH=amd64 go build -o app.exe

windows 环境下编译 mac、linux 环境可执行文件:

# 编译 arm 架构(windows 环境下编译)
GOOS=linux GOARCH=arm GOARM=7 go build

# 编译 amd 架构(windows 环境下编译)
GOOS=linux GOARCH=arm GOARM=7 go build

注意⚠️:

  • 编译后可直接运行,无需依赖 go 环境

  • 赋予文件可执行权限:chmod +x 编译后可执行文件

  • 编译后建议在对应的平台进行验证,避免出现问题

常见问题

Q1:编译的 Linux 程序传到服务器后,执行时提示“Permission denied”?

这是没有执行权限导致的,在 Linux 终端执行 chmod +x 程序名 赋予权限,比如 chmod +x linux_test,再执行 ./linux_test 即可。

Q2:编译 Mac 程序后,传到 Mac 上运行提示“无法打开,因为开发者无法验证”?

这是 Mac 的安全机制导致的,

解决方法:系统偏好设置 → 安全性与隐私 → 通用 → 点击“仍要打开”,确认后即可运行。

Q3:编译 32 位程序时提示“undefined: runtime/internal/syscall.Syscall”?

GO 1.16 以后对 32 位系统的支持需要额外配置,编译时加上 CGO_ENABLED=0 即可,

比如 Windows 编译 32 位程序:set CGO_ENABLED=0 && set GOOS=windows && set GOARCH=386 && go build

Q4:程序里有中文,编译后运行显示乱码怎么办?

编译时指定编码格式,在 go build 前加 set LANG=zh_CN.UTF-8(Windows)或 export LANG=zh_CN.UTF-8(Mac/Linux),确保编译和运行环境的编码一致。

总结

GO 交叉编译的优势在于“简单、高效、无需额外依赖”,核心就是通过 GOOSGOARCH 两个环境变量控制目标平台,再配合 go build 命令即可完成。

实际开发中,建议把常用的编译命令写成脚本,比如每次发布时运行脚本,一键生成所有平台的程序,大大提升交付效率。

需要注意的是,如果你的程序用到了 CGO(调用 C 语言库),交叉编译会复杂一些,需要额外配置 C 语言的交叉编译链,但大部分纯 GO 开发的程序都不用考虑这个问题。

总的来说,GO 的交叉编译是“开箱即用”的核心优势之一,掌握它能让你在跨平台开发中少走很多弯路,尤其是在云原生和物联网场景下,更是必备技能。

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/go-cross-compile/

备用原文链接: https://blog.fiveyoboy.com/articles/go-cross-compile/