2013-07-18 81 views
19

Go包A由3個.go文件組成,我使用每個文件中另一個包B中的函數。Go包初始化

我必須在這三個文件的每一個的開始處導入包B,但是包B實際初始化了3次還是隻有1次?

回答

31

簡答:初始化只執行一次。

龍回答:引用的相關規範部分 - Program execution

沒有進口數據包通過其全包級變量賦初值,然後調用任何數據包級的功能與名稱初始化並簽字

func init() 

在其來源中定義。名稱爲init的程序包範圍或文件範圍標識符只能聲明爲具有此簽名的函數。即使在單個源文件中也可以定義多個這樣的函數;它們以未指定的順序執行。

在一個包中,包級變量被初始化,並根據參考順序確定常量值:如果A的初始化因子取決於B,則A將在B之後被設置。依賴關係分析不依賴於正在初始化的項目的實際值,僅在源文件中出現。 A取決於B,如果A的值包含提到的B,包含一個初始化符提到B的值,或者遞歸地提到一個提到B的函數。如果這樣的依賴關係形成一個循環,這是一個錯誤。如果兩個項目不相互依賴,它們將按照它們出現在源代碼中的順序進行初始化,可能以多個文件的形式呈現給編譯器。由於依賴性分析每個包完成的,它可以產生未指定的結果,如果A的初始值設定調用引用B.

init功能不能被稱爲從在程序中任何地方的另一包中定義的功能。特別是,不能明確調用init,也不能將指向init的指針指定給函數變量。

如果包有導入,則在初始化包本身之前,導入的包將被初始化。如果多個軟件包導入一個軟件包P,則P只會初始化一次。

通過構造導入包可確保在初始化中不存在循環依賴關係。

一個完整的程序是通過將一個名爲的主包的單一未導入包與它所導入的所有包連接起來創建的。主包必須有包名稱main並聲明函數main,它不接受任何參數並且不返回任何值。

func main() { … } 

程序執行通過初始化主包,然後調用函數main開始。當函數main返回時,程序退出。它不會等待其他(非主要)goroutines完成。

程序包初始化變量初始化和調用init函數 - 在單個goroutine中,按順序一次發生一個程序包。一個init函數可能會啓動其他的goutoutine,它可以與初始化代碼同時運行。但是,初始化始終對init函數進行排序:直到前一個返回,它纔會開始下一個init