2017-03-16 60 views
2

我們已經構建了一個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程序中刪除未使用的代碼?

+2

您使用的是哪個版本的Go?因爲如果沒有調用subplay.B(),那麼在我的可執行文件中''secret secret字符串''不會出現**(Go 1.8,針對linux和windows)! – icza

回答

5

編譯器已經這樣做了。所有代碼都以包文件結尾(.a),但在可執行二進制文件中,Go工具並不包括來自導入包的所有內容,只包含需要的內容(或者更確切地說:它排除了它可能無法訪問的內容)。

查看可能的重複Splitting client/server code

這裏需要注意的一點是:如果一個導入的包(從中只包含你引用的東西)導入其他包,這當然必須遞歸地完成。

例如,如果你把這個包:

package subplay 

func A() {} 

並調用由它沒有什麼:

package main 

import _ "play/subplay" 

func main() { 
} 

結果二進制(轉到1.8,Linux操作系統,AMD64)將是960134個字節(大約1 MB)。

如果更改subplay導入net/http

package subplay 

import _ "net/http" 

func A() {} 

但仍然沒有從net/http叫什麼,結果將是:5370935字節(大約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() 
} 

結果二進制增長:5877919個字節

如果更改http.ListenAndServe()http.ListenAndServeTLS()

func A() { 
    http.ListenAndServeTLS("", "", "", nil) 
} 

結果二進制是:6041535字節

如您所見,編譯到可執行二進制文件中的內容取決於您從導入的軟件包中調用/使用

另外不要忘記,Go是一種靜態鏈接的語言,結果可執行二進制文件必須包含它需要的所有內容。查看相關問題:Reason for huge size of compiled executable of Go

+0

嗨Icza,謝謝你的迴應。我們看到了不同的結果。查看上面的更新消息並提供詳細信息。預先感謝您對此進行調查! –

+0

值得注意的是,導入一個包,不管你是否使用它,都會導致包變量被初始化並且運行'init()'函數。這些可以引用包的其他部分,然後引用其他部分......所以,僅僅因爲你沒有在包中引用任何東西,並不意味着導入它會使整個包不被使用,或者編譯器將會能夠消除它。 – Adrian

+0

@Adrian是的,這正是我的第二個例子應該證明的:沒有使用'subplay',但可執行二進制文件增加了4 MB,因爲它引用了'net/http'。 – icza

0

如果你不介意限制(插件需要Go 1.8,目前只能在Linux上運行),你可以將你的軟件包變成plugin

由於您使用的是Windows,因此這不適合您。

+0

每個插件本身都是靜態鏈接的,因此會更大。 –

+0

將軟件包解壓縮到插件中意味着軟件包二進制代碼只能在一個.so文件中,而不是在實用程序可執行文件中。因此,根據要求將該代碼從實用程序中刪除。當然插件本身是靜態鏈接的,但實用程序動態加載它們,它們不會導入它。 – Zoyd

+1

雖然插件可能有助於減少可執行二進制+插件文件的大小,但它們也可能會增加它!例如,如果插件導入'fmt',並且您的主應用程序也導入了'fmt',則包含在可執行二進制文件和插件文件中的fmt包將被包含!更何況加載和使用插件比導入和使用包要方便得多。此外,更不用說性能...... – icza