我们已经构建了一个Go包,供我们许多人使用。
它是使用标准import ("package-name")方法导入的。
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程序中删除未使用的代码?
编译器已经做到了。所有代码都以包文件(.a)结尾,但是在可执行二进制文件中,Go工具并不包括导入包中的所有内容,仅包括所需的内容(或更确切地说,它排除了可能无法访问的内容)。
.a
这里要注意的一件事:如果一个导入的包(您只想从中包含您所引用的内容)导入了其他包,那么这当然必须递归地完成。
例如,如果您导入此程序包:
package subplay func A() {}
并从中调用任何内容:
package main import _ "play/subplay" func main() { }
结果二进制文件(Go 1.8,linux,amd64)将为960,134字节(大约1 MB)。
如果更改subplay为导入net/http:
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
subplay.A()
当您将main包更改为call时subplay.A():
结果二进制数 增长:5,877,919字节 !
如果更改http.ListenAndServe()为http.ListenAndServeTLS():
http.ListenAndServe()
http.ListenAndServeTLS()
func A() { http.ListenAndServeTLS("", "", "", nil) }
结果二进制为: 6,041,535字节 。
如您所见,编译到可执行二进制文件中的内容 确实取决于您 从导入包中 调用/使用 的内容。
同样不要忘记Go是一种静态链接的语言,结果可执行二进制文件必须包含它需要的所有内容。