如果我导入" fmt"在同一个Go包中的2个文件的顶部,它会编译两次吗?

时间:2017-06-10 17:55:04

标签: go build

我正在使用go 1.6(我需要更新)。我们假设我在一个软件包中有2个文件,并且我在其中都使用了fmt软件包。您必须在这两个文件中显式导入fmt,或者编译器抛出错误,这是否意味着它将fmt二进制文件存储在我的可执行文件中两次?

1 个答案:

答案 0 :(得分:5)

不,那将是一个非常糟糕的设计(最后读取异常)。顺便说一下,检查这个很容易,创建一个名为a的包,由2个文件组成:aa.goab.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文件夹中出售的,并且包裹是指这个被出售的包裹,那么它被认为与原始包裹(被出售)不同,如果原始包裹也被另一个包裹引用,则两者都将被包含在可执行二进制文件中(但它们不被认为是相同的,被销售者的完整路径与原始文件的完整路径不同)。