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程序中删除未使用的代码?
编译器已经这样做了.所有代码都以包文件(.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的已编译可执行文件的大小原因