0%

《十万个为什么》Go可执行文件为什么这么大

编译下面代码试试

1
2
3
4
5
6
7
8
9
package main

import (
"fmt"
)

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

在MAC上,使用 go build ./ 编译出可执行文件,发现可执行文件的大小是2.1M

而一个C语言的HelloWorld

1
2
3
int main () {
printf("Hello World!");
}

gcc main.c 编译出来仅仅只有8.2k

相距如此大,为什么?

原因就是本例中,Golang编译是静态编译,其运行时所有内容都被编译到可执行文件中了

而C编译则是动态编译,其运行时则是以动态链接库的形式存放在文件系统中,没有被编译到可执行文件中

那为什么Golang不使用动态编译呢?

理论上Golang运行时当然可以构建出一个动态链接库,然后像C运行库一样存放在文件系统中供所有Golang程序动态链接调用

但是凡事都有个过程

Golang团队也想实现这个伟大功能,只不过目前的版本(v1.14.1)只能支持linux_amd64平台

假如我现在一个linux_amd64平台平台上,我可以这样构建出一个Golang运行时的动态链接库并放到文件系统的合适位置

1
go install -buildmode=shared std

会生成libstd.so文件,被放入目录/usr/local/go/pkg/linux_amd64_dynlink/

然后使用 go build -linkshared ./ 编译一下上面的代码,发现可执行文件只有24k,且可以正常运行

试想一下,如果不久的将来,运行时的动态链接库能够在主流平台都能构建出动态链接库

那么所有Golang程序都可以使用动态链接的方式编译,这样的话可执行文件的大小将得到质的改变

java中,同一个jar包可以在所有平台上运行,但jar并不是二进制文件,需要虚拟机解释执行,这一点相对会有性能损耗。Golang没有采用这种方式




微信关注我,及时接收最新技术文章