我正在使用go 1.6(我需要更新)。我们假设我在一个软件包中有2个文件,并且我在其中都使用了fmt
软件包。您必须在这两个文件中显式导入fmt
,或者编译器抛出错误,这是否意味着它将fmt
二进制文件存储在我的可执行文件中两次?
答案 0 :(得分:5)
不,那将是一个非常糟糕的设计(最后读取异常)。顺便说一下,检查这个很容易,创建一个名为a
的包,由2个文件组成:aa.go
和ab.go
。同时导入fmt
。生成可执行文件(例如go build
,必须在main
包上调用)并检查其大小。现在将使用ab.go
包的fmt
的所有代码移至aa.go
,然后从fmt
移除ab.go
导入。再次生成可执行文件。它们的大小相同。
包的完整路径标识。无论有多少个文件(同一个软件包)或多少个(不同的)软件包引用一个软件包,该软件包只会在最终的可执行二进制文件中包含一次。
另请注意,并非所有内容都包含在可执行二进制文件中的已使用包中。某些未使用/提及的内容可能会被排除在外。有关详细信息,请参阅Splitting client/server code;和How to remove unused code at compile time?
但有一个例外,即Go 1.8中引入的plugins。插件引用的包将包含在已编译的插件中 - 它们必须是 - ,因为插件无法保证将加载它的可执行二进制文件中可用的包。因此,如果包fmt
引用main
包,也通过插件引用,fmt
包的代码将包含在两者中(在可执行二进制文件和编译中)插入)。应该注意的是,即使fmt
包的代码将出现两次(一次在可执行文件中,一次在插件中),仍然只有一个"实例"运行时中的包(在内存中)(例如,它的全局变量将有一个实例,并且只会初始化一次)。
" edge"案例是vendored packages。如果包裹是在vendor
文件夹中出售的,并且包裹是指这个被出售的包裹,那么它被认为与原始包裹(被出售)不同,如果原始包裹也被另一个包裹引用,则两者都将被包含在可执行二进制文件中(但它们不被认为是相同的,被销售者的完整路径与原始文件的完整路径不同)。