一尘不染

如何在编译时删除未使用的代码?

go

我们已经构建了一个Go包,供我们许多人使用。

它是使用标准import ("package-name")方法导入的。

但是,在编译时,我们所有的实用程序(包括很小的实用程序)最终都是很大的二进制文件。

我们提取了实用程序中的所有字符串,并发现整个软件包都被编译到每个实用程序中。包括那些实用程序未使用的功能。

编辑1:

谢谢回答这个问题的人。

这是我们所看到的:

main.go

package main

import "play/subplay"

func main() {
    subplay.A()
}

play / subplay.go

package subplay

func A() {
    fmt.Printf("this is function A()")
}

func B() {
    fmt.Printf("secret string")
}

永远不会调用函数B()。但是,在构建二进制文件之后,我们在main.exe中找到了字符串“ secret string”。

我们如何在编译时从Go程序中删除未使用的代码?


阅读 284

收藏
2020-07-02

共1个答案

一尘不染

编译器已经做到了。所有代码都以包文件(.a)结尾,但是在可执行二进制文件中,Go工具并不包括导入包中的所有内容,仅包括所需的内容(或更确切地说,它排除了可能无法访问的内容)。

这里要注意的一件事:如果一个导入的包(您只想从中包含您所引用的内容)导入了其他包,那么这当然必须递归地完成。

例如,如果您导入此程序包:

package subplay

func A() {}

并从中调用任何内容:

package main

import _ "play/subplay"

func main() {
}

结果二进制文件(Go 1.8,linux,amd64)将为960,134字节(大约1 MB)。

如果更改subplay为导入net/http

package subplay

import _ "net/http"

func A() {}

但是仍然不要从中调用任何内容net/http,结果将是: 5,370,935字节 (大约5
MB)!(请注意,net/http还要导入其他39个软件包!)

现在,如果您开始使用以下内容net/http

package subplay

import "net/http"

func A() {
    http.ListenAndServe("", nil)
}

但是在main程序包中您仍然不调用subplay.A(),可执行二进制文件的大小 不会改变:仍然为5,370,935字节

当您将main包更改为call时subplay.A()

package main

import "play/subplay"

func main() {
    subplay.A()
}

结果二进制数 增长:5,877,919字节

如果更改http.ListenAndServe()http.ListenAndServeTLS()

func A() {
    http.ListenAndServeTLS("", "", "", nil)
}

结果二进制为: 6,041,535字节

如您所见,编译到可执行二进制文件中的内容 确实取决于您 从导入包中 调用/使用 的内容。

同样不要忘记Go是一种静态链接的语言,结果可执行二进制文件必须包含它需要的所有内容。

2020-07-02