我们已经构建了一个我们很多人都使用的Go包。
使用标准import ("package-name")
方法导入。
在编译时,我们所有的实用程序,包括非常小的实用程序,最终都是非常大的二进制文件。
我们已经提取了实用程序中的所有字符串,并发现整个包正在编译到每个实用程序中。包括那些实用程序未使用的函数。
编辑1:
感谢回答这个问题的人们。
以下是我们所看到的:
main.go
package main
import "play/subplay"
func main() {
subplay.A()
}
播放/ subplay.go
package subplay
func A() {
fmt.Printf("this is function A()")
}
func B() {
fmt.Printf("secret string")
}
永远不会调用函数B()。然而,在构建二进制文件之后,我们在main.exe中找到字符串“secret string”。
如何在编译时从Go程序中删除未使用的代码?
答案 0 :(得分:7)
编译器已经这样做了。所有代码都以包文件(.a
)结束,但在可执行二进制文件中,Go工具不包含导入包中的所有内容,只包含所需内容(或更准确地说:它排除了可以证明无法访问的内容)。
请参阅可能的重复Splitting client/server code。
这里要注意的一件事:如果一个导入的包(你只想包含你引用的东西)导入其他包,那么当然必须以递归的方式完成。
例如,如果您导入此包:
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 other packages!)
现在,如果您继续使用net/http
中的内容:
package subplay
import "net/http"
func A() {
http.ListenAndServe("", nil)
}
但是在main
包中你仍然没有调用subplay.A()
,可执行二进制文件的大小不会改变:仍为5,370,935字节!
当您更改main
包以致电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是一种静态链接语言,结果可执行二进制文件必须包含它所需的一切。请参阅相关问题:Reason for huge size of compiled executable of Go
答案 1 :(得分:0)
如果你不介意这些限制(插件需要Go 1.8,目前只适用于Linux),你可以将你的软件包变成plugin。
[edit]由于您使用的是Windows,因此无法选择。