如何减less编译的文件大小?

让我们比较一下c:Hello_world.c:

#include<stdio.h> int main(){ printf("Hello world!"); } 

Hello_world.go:

 package main import "fmt" func main(){ fmt.Printf("Hello world!") } 

编译两者:

 $gcc Hello_world.c -o Hello_c $8g Hello_world.go -o Hello_go.8 $8l Hello_go.8 -o Hello_go 

还有,这是什么?

 $ls -ls ... 5,4K 2010-10-05 11:09 Hello_c ... 991K 2010-10-05 11:17 Hello_go 

约1Mb你好,世界。 你在跟我开玩笑吗? 我做错了什么?

(只有Hello_go – > 893K)

这是一个文件较大的问题吗? 我不知道去,但我会假设它静态链接一些运行时库,而不是C程序的情况。 但是,只要你的程序变大,这可能就不用担心了。

如此处所述,静态链接Go运行时是默认的。 该页面还会告诉您如何设置dynamic链接。

如果您使用的是基于Unix的系统(例如Linux或Mac OSX),则可以尝试通过使用-s标志构build可执行文件来删除可执行文件中包含的debugging信息:

 go build -ldflags "-s" prog.go 

我不知道如何在Windows中做到这一点,但在Linux中,文件大小大大降低。

欲了解更多详情,请访问GDB的页面: http : //golang.org/doc/gdb

2016年答案:

1.使用Go 1.7

2.编译go build -ldflags "-s -w"

 ➜ ls -lh hello -rwxr-xr-x 1 oneofone oneofone 976K May 26 20:49 hello* 

3.然后用upx ,自1.6以后不再需要goupx

 ➜ ls -lh hello -rwxr-xr-x 1 oneofone oneofone 367K May 26 20:49 hello* 

Go二进制文件很大,因为它们是静态链接的(除了使用cgo的库绑定)。 尝试静态链接一个C程序,你会看到它增长到一个可比的大小。

如果这真的是你的一个问题(我很难相信),你可以使用gccgo进行编译并dynamic链接。

您应该得到goupx ,它将“修复”Golang ELF可执行文件以与upx一起工作。 在某些情况下,我已经有约78%的文件大小缩减~16MB >> ~3MB

压缩比通常趋于25%,所以值得一试:

 $ go get github.com/pwaller/goupx $ go build -o filename $ goupx filename 

>>

 2014/12/25 10:10:54 File fixed! File size Ratio Format Name -------------------- ------ ----------- ----------- 16271132 -> 3647116 22.41% linux/ElfAMD filename Packed 1 file. 

EXTRA: -s标志(strip)可以缩小bin文件甚至更多的goupx -s filename

更紧凑的hello-world示例:

 package main func main() { print("Hello world!") } 

我们是滑雪大fmt包,明显减less二进制:

  $ go build hello.go $ ls -lh hello ... 259K ... hello2 $ strip hello $ ls -lh hello ... 162K ... hello2 

不像C那么紧凑,但是用K而不是M来衡量。好吧,这不是一般的方法,只是展示了一些优化尺寸的方法:使用strip并尝试使用最小包。 无论如何,Go不是制作小型二进制文件的语言。

创build一个名为main.go的文件,让我们试试简单的hello world程序。

 package main import "fmt" func main(){ fmt.Println("Hello World!") } 

我使用去版本1.9.1

 $ go version go version go1.9.1 linux/amd64 

使用标准的go build命令进行编译。

 $ go build main.go $ ls -lh -rwxr-xr-xx 1 nil nil 1.8M Oct 27 07:47 main 

让我们再次编译一下,但是如上所示,使用ldflags

 $ go build -ldflags "-s -w" main.go $ ls -lh -rwxr-xr-xx 1 nil nil 1.2M Oct 27 08:15 main 

文件大小减less了30%。

现在,让我们使用gccgo

 $ go version go version go1.8.1 gccgo (GCC) 7.2.0 linux/amd64 

build设与gccgo

 $ go build main.go $ ls -lh -rwxr-xr-x 1 nil nil 34K Oct 27 12:18 main 

二进制大小减less了近100%。 让我们再次尝试使用gccgo构buildmain.go ,但使用构build标志,

 $ go build -gccgoflags "-s -w" main.go -rwxr-xr-x 1 nil nil 23K Oct 27 13:02 main 

警告:由于gccgo二进制文件是dynamic链接的。 如果你有一个非常大的二进制文件,你用gccgo编译的二进制文件不会减less100%,但是它的大小会减less很多。

与gc相比,gccgo编译代码较慢,但支持更强大的优化,所以gccgo构build的CPU绑定程序通常运行得更快。 多年来在GCC中实现的所有优化都是可用的,包括内联,循环优化,vector化,指令调度等等。 尽pipe并不总能生成更好的代码,但在某些情况下,使用gccgo编译的程序运行速度可能会提高30%。

预计GCC 7版本将包含Go 1.8用户库的完整实现。 和早期版本一样,Go 1.8运行时没有完全合并,但Go程序不应该看到它。

优点:

  1. 缩小尺寸
  2. 优化。

缺点

  1. 不能使用最新版本的go

你可以看到这里和这里 。

该二进制文件默认包含垃圾收集器,pipe理go例程的调度系统以及所有导入的库。

结果是大约1 Mb的最小的大小。

从Go 1.8开始,你也可以使用新的插件系统将你的二进制文件分成类似于共享库的东西。 对于这个版本,它只能在Linux上运行,但其他平台将来可能会被支持。

https://tip.golang.org/pkg/plugin/