在编译go程序过程中,我们有时候会需要减少程序的体积,特别是在容器化部署过程中,这会加快images的下载速度。
这里介绍了几种减少体积的方式。首先对比下go和c 的区别
Go VS C 二进制
hello.go1
2
3
4
5
6
7package main
import "fmt"
func main() {
fmt.Println("hello world")
}
hello.c1
2
3
4
5
6#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
1 | $ go build -o hello hello.go |
1 | $ ls -l |
golang 连接的参数:1
2
3
4
5$ go tool link -h
usage: link [options] main.o
-s disable symbol table # 去掉符号表
-w disable DWARF generation # 去掉调试信息
ELF
先来看下 C 的:
1 | $ readelf -h a.out |
1 | $ readelf -d a.out |
再来看下 go 的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21$ readelf -h hello
ELF 头:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
类别: ELF64
数据: 2 补码,小端序 (little endian)
版本: 1 (current)
OS/ABI: UNIX - System V
ABI 版本: 0
类型: EXEC (可执行文件)
系统架构: Advanced Micro Devices X86-64
版本: 0x1
入口点地址: 0x451fa0
程序头起点: 64 (bytes into file)
Start of section headers: 456 (bytes into file)
标志: 0x0
本头的大小: 64 (字节)
程序头大小: 56 (字节)
Number of program headers: 7
节头大小: 64 (字节)
节头数量: 13
字符串表索引节头: 3
1 | $ readelf -d hello |
The linker in the gc toolchain creates statically-linked binaries by default. All Go binaries therefore
include the Go runtime, along with the run-time type information necessary to support dynamic type checks, > reflection, and even panic-time stack traces.
A simple C “hello, world” program compiled and linked statically using gcc on Linux is around 750 kB,
including an implementation of printf. An equivalent Go program using fmt.Printf weighs a couple of
megabytes, but that includes more powerful run-time support and type and debugging information.
所以,为什么 go 二进制比 C 大很多就比较明显了。
golang 静态编译,不依赖动态库。
如何减小 go 二进制文件大小
-ldflags
上面已经提到了过了。1
$ go build -ldflags "-s -w" xxx.go
UPX
1 | Commands: |
禁止gc优化和内联
1 | go build -gcflags '-N -l' |
说明:
-N 禁止编译优化
-l 禁止内联,禁止内联也可以一定程度上减小可执行程序大小
可以使用 go tool compile –help 查看 gcflags 各参数含义
参考:
https://blog.csdn.net/fengfengdiandia/article/details/84582076