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

ABC*_*ABC 3 compilation go compiler-optimization

我们已经构建了一个我们很多人都使用的Go包.

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

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

我们已经提取了实用程序中的所有字符串,并发现整个包正在编译到每个实用程序中.包括那些实用程序未使用的函数.

编辑1:

感谢回答这个问题的人们.

这是我们所看到的:

main.go

package main

import "play/subplay"

func main() {
    subplay.A()
}
Run Code Online (Sandbox Code Playgroud)

播放/ subplay.go

package subplay

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

func B() {
    fmt.Printf("secret string")
}
Run Code Online (Sandbox Code Playgroud)

函数B()永远不会被调用.然而,在构建二进制文件之后,我们在main.exe中找到字符串"secret string".

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

icz*_*cza 7

编译器已经这样做了.所有代码都以包文件(.a)结尾,但在可执行二进制文件中,Go工具不包含导入包中的所有内容,只包含所需内容(或更准确地说:它排除了可以证明无法访问的内容).

查看可能重复的拆分客户端/服务器代码.

这里要注意的一件事是:如果一个导入的包(你只想包含你引用的东西)导入其他包,那么当然必须递归地完成.

例如,如果您导入此包:

package subplay

func A() {}
Run Code Online (Sandbox Code Playgroud)

并且不要求它:

package main

import _ "play/subplay"

func main() {
}
Run Code Online (Sandbox Code Playgroud)

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

如果您更改subplay为导入net/http:

package subplay

import _ "net/http"

func A() {}
Run Code Online (Sandbox Code Playgroud)

但仍然不会调用任何东西net/http,结果将是:5,370,935字节(大约5 MB)!(注意,net/http还要导入39个其他包!)

现在,如果您继续使用以下内容net/http:

package subplay

import "net/http"

func A() {
    http.ListenAndServe("", nil)
}
Run Code Online (Sandbox Code Playgroud)

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

当您更改main要调用的包时subplay.A():

package main

import "play/subplay"

func main() {
    subplay.A()
}
Run Code Online (Sandbox Code Playgroud)

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

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

func A() {
    http.ListenAndServeTLS("", "", "", nil)
}
Run Code Online (Sandbox Code Playgroud)

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

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

另外不要忘记Go是一种静态链接语言,结果可执行二进制文件必须包含它所需的一切.请参阅相关问题:Go的已编译可执行文件的大小原因