Go 和 Rust 编译后程序大小对比
学习笔记作者:admin日期:2025-09-26点击:11
摘要:Rust 编译后的程序通常比 Go 更小,尤其是在启用优化和代码瘦身选项后。Go 默认包含运行时和调试信息,而 Rust 则更轻量,适合对体积敏感的场景。
1. 默认编译输出大小对比
语言 | 默认编译大小特点 |
---|---|
Go | 默认生成的二进制文件较大,包含完整的运行时(GC、goroutine 调度器等)、调试信息和标准库静态链接。即使一个简单的 "Hello World" 也可能在几 MB 左右(例如 2-5 MB)。 |
Rust | 默认生成的二进制文件更小,尤其是对小型项目。Rust 是零成本抽象语言,标准库精简,且默认不包含垃圾回收等运行时。Hello World 可能只有几百 KB。 |
2. 影响二进制大小的关键因素
Go
- 静态链接:Go 默认将所有依赖(包括运行时)打包进一个二进制文件。
- 运行时开销:包含 GC、goroutine 调度、反射、类型信息等,即使不用也包含。
- 调试信息:默认包含 DWARF 调试信息,显著增加体积。
- 可优化:
go build -ldflags="-s -w"
去除符号表和调试信息,可大幅减小体积。 - UPX 压缩:进一步减小(但运行时解压)。
Rust
- 零成本抽象:未使用的代码不会被编译进去(得益于单态化和死代码消除)。
- 运行时极小:无 GC,运行时非常轻量,甚至可以使用
no_std
编写无运行时程序。 - 编译器优化:通过
LTO
(链接时优化)、opt-level=s
(大小优化)等可显著减小体积。 - 可配置:可通过
strip
去除调试符号,或使用cargo-bloat
分析体积来源。
3. 示例对比(Hello World)
// main.go
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
// main.rs
fn main() {
println!("Hello, World!");
}
语言 | 编译命令 | 输出大小(约) |
---|---|---|
Go | go build main.go |
2.5 MB |
Go | go build -ldflags="-s -w" main.go |
1.3 MB |
Rust | cargo build --release |
300 KB |
Rust | cargo build --release + strip |
~150 KB |
4. 什么时候 Go 可能更小?
- 几乎不会。
- 除非:
- Rust 项目使用了大量泛型(导致代码膨胀)。
- Go 程序极简且经过深度优化(如 TinyGo,用于嵌入式,可生成极小二进制)。
TinyGo 是一个特例:它使用 LLVM,专为嵌入式设计,可生成比 Rust 更小的二进制(在微控制器上),但功能受限。
5. 总结:哪个更小?
Rust 通常生成更小的二进制文件,尤其适合对体积敏感的场景(CLI 工具、嵌入式、WASM)。
Go 二进制较大,但开发效率高、部署方便(单文件、自带运行时),适合后端服务。
6. 如何减小体积?
Go
go build -ldflags="-s -w" -o main main.go
# 进一步压缩
upx --best --lzma main
Rust
[profile.release]
opt-level = "s" # 或 "z"(最小尺寸)
lto = true
strip = true # 自动 strip(需 nightly)
# 编译后 strip
strip target/release/main
# 或使用 upx
upx --best --lzma target/release/main
结论
如果你关心二进制大小,Rust 通常是更好的选择。
如果你更看重开发效率和部署简单,Go 仍然非常有竞争力,尽管体积大一些。