减小Go代码编译后的二进制体积

TrumanWong
4/17/2025
TrumanWong

1 基线用例

Go 语言编译器编译出来的二进制文件体积通常比较大,尤其是使用了第三方库的情况下。因此减小编译后的二进制文件体积,有助于加快程序的发布和安装速度。接下来,我们将从编译选项优化和使用第三方压缩工具两个方面,介绍在 Go 语言中如何有效地缩减生成文件的大小。

如下我们有一个简单的 Go 语言程序,使用了 gin 框架。

package main

import "github.com/gin-gonic/gin"

func main() {
	// 启动gin
	r := gin.Default()
	// 启动服务
	r.Run(":8080")
}

使用默认选项编译该程序,编译后的程序大小约为 12M。

$ ls -alh server
-rwxr-xr-x 1 wong 197121 12M Apr 16 18:16 server*

2 编译选项

Go 编译器默认编译的二进制文件包含了调试信息和符号表等信息,这些信息在调试时非常有用,但在发布时并不需要。我们可以使用 -ldflags 选项来去掉这些信息。

$ go build -ldflags="-s -w" -o server
$ ls -alh server
-rwxr-xr-x 1 wong 197121 8.0M Apr 16 18:18 server*

体积从 12M 下降到 8M,下降约 33%。

3 使用 upx 减小体积

3.1 upx 安装

UPX is an advanced executable file compressor. UPX will typically reduce the file size of programs and DLLs by around 50%-70%, thus reducing disk space, network load times, download times and other distribution and storage costs.

upx 是一个常用的压缩动态库和可执行文件的工具,通常可减少 50-70% 的体积。

upx 的安装方式非常简单,我们可以直接从 github 下载最新的 release 版本,支持 Windows 和 Linux,在 Linux 或 Mac 可以直接使用包管理工具安装。例如:

# Ubunntu
$ sudo apt-get install upx
# Fedora/CentOS/RHEL
$ sudo yum install upx
# Mac
$ brew install upx

3.2 仅使用 upx

upx 有很多参数,最重要的则是压缩率,1-91 代表最低压缩率,9 代表最高压缩率。

接下来我们使用 upx 来压缩编译后的二进制文件。

$ go build -o server && upx -9 server
$ ls -alh server
-rwxr-xr-x 1 wong 197121 6.0M Apr 16 18:31 server*

可以看到,使用 upx 后,可执行文件的体积从 12M 缩小到了 6M,缩小了 50%。

3.3 upx 和编译选项组合

$ go build -ldflags="-s -w" -o server && upx -9 server
$ ls -alh server
-rwxr-xr-x 1 wong 197121 2.7M Apr 16 18:32 server*

使用编译选项后,体积从原来的 12M 下降了 20% 到 8M,使用 upx 压缩后,体积进一步下降 66% 到 2.7M。累进下降约 77%。

3.4 upx 的原理

upx 压缩后的程序和压缩前的程序一样,无需解压仍然能够正常地运行,这种压缩方法称之为带壳压缩,压缩包含两个部分:

执行时,也包含两个部分:

也就是说,upx 在程序执行时,会有额外的解压动作,不过这个耗时几乎可以忽略。

如果对编译后的体积没什么要求的情况下,可以不使用 upx 来压缩。一般在服务器端独立运行的后台服务,无需压缩体积。