Go 中的 init 函數

來源:互聯網
上載者:User
main 標識符是隨處可見的,每一個 Go 程式都是從一個叫 main 的包中的 main 函數開始的,當 main 函數返回時,程式執行結束。 init 函數也扮演著特殊的角色,接下來我們將描述下 init 函數的屬性並介紹下怎麼使用它們。init 函數在包層級被定義,主要用於:- 初始化那些不能被初始設定式完成初始化的變數- 檢查或者修複程式的狀態- 註冊- 僅執行一次的計算- 更多其它場合除了下面將要討論到的一些差異外,你還可以在正則函數中放置任何[有效](https://golang.org/ref/spec#FunctionBody)的內容。## 包的初始化要想使用匯入的包首先需要初始化它,這是由golang的運行系統完成的,主要包括(順序很重要):1. 初始化匯入的包(遞迴的定義)2. 在包層級為聲明的變數計算並分配初始值3. 執行包內的 init 函數(下面的空白標識符就是一個例子)> 不管包被匯入多少次,都只會被初始化一次。## 順序Go 的包中有很多的檔案,如果變數和函數在包的多個檔案當中,那麼變數的初始化和 init 函數的調用順序又是什麼樣的呢?首先,初始化依賴機制會啟動(更多 [Go 中的初始化依賴](https://studygolang.com/articles/13158))當初始化依賴機制完成的時候,就需要決定 `a.go` 和 `z.go` 中的初始設定變數誰會被更早的處理,而這要取決於呈現給編譯器的檔案順序。如果 `z.go` 先被傳遞到構建系統,那麼變數的初始化就會比在 `a.go` 中先一步完成,這也同樣適用於 init 函數的觸發。Go 語言規範建議我們始終使用相同的順序傳遞,即按照詞法順序傳遞包中的檔案名稱:> 為了保證可重複的初始化行為,構建系統鼓勵按照詞法檔案名稱的順序將屬於同一個包中的多個檔案呈現給編譯器。但依賴特定順序對於不關注可移植性的程式是一種方式(譯註:但不建議依賴 init 初始化順序)。讓我們來看一個例子,看看它們是如何一起工作的:### sandbox.go```gopackage mainimport "fmt"var _ int64 = s()func init() { fmt.Println("init in sandbox.go")}func s() int64 { fmt.Println("calling s() in sandbox.go") return 1}func main() { fmt.Println("main")}```### a.go```gopackage mainimport "fmt"var _ int64 = a()func init() { fmt.Println("init in a.go")}func a() int64 { fmt.Println("calling a() in a.go") return 2}```### z.go```gopackage mainimport "fmt"var _ int64 = z()func init() { fmt.Println("init in z.go")}func z() int64 { fmt.Println("calling z() in z.go") return 3}```### 程式輸出:```calling a() in a.gocalling s() in sandbox.gocalling z() in z.goinit in a.goinit in sandbox.goinit in z.gomain```## 屬性init 函數不需要參數並且也不返回任何值,與 main 類似,標識符 init 沒有被聲明所以也就不能被引用:```gopackage mainimport "fmt"func init() { fmt.Println("init")}func main() { init()}```在編譯時間這裡會給出一個 “undefined:init” 錯誤。( init 函數不能被引用)> 正式的來講 init 標示符不會引入綁定,就像空白標示符('_')表現的一樣。在同一個包或者檔案當中可以定義很多的 init 函數:### sandbox.go```gopackage mainimport "fmt"func init() { fmt.Println("init 1")}func init() { fmt.Println("init 2")}func main() { fmt.Println("main")}```### utils.go```gopackage mainimport "fmt"func init() { fmt.Println("init 3")}```### 輸出:```init 1init 2init 3main```init 函數在標準庫中也被頻繁的使用,例如:[*main*](https://github.com/golang/go/blob/2878cf14f3bb4c097771e50a481fec43962d7401/src/math/pow10.go#L33), [*bzip2*](https://github.com/golang/go/blob/2878cf14f3bb4c097771e50a481fec43962d7401/src/compress/bzip2/bzip2.go#L479)還有 [*image*](https://github.com/golang/go/blob/2d573eee8ae532a3720ef4efbff9c8f42b6e8217/src/image/gif/reader.go#L511)包。...init 函數最常見的用法就是為初始設定式中不能被計算的那部分分配一個值:```govar precomputed = [20]float64{}func init() { var current float64 = 1 precomputed[0] = current for i := 1; i < len(precomputed); i++ { precomputed[i] = precomputed[i-1] * 1.2 }}```使用 for 迴圈作為[*運算式*](https://golang.org/ref/spec#Expression)(Go 語言中的語句)是不可能的,所以將這些放到 init 函數中就能夠很好的解決這些問題。## 僅僅為了使用包的副作用(包的初始化)而匯入包Go 語言對沒有使用的匯入是非常嚴格的。有時候程式員匯入一個包可能只想要使用 init 函數的功能,例如一些引導工作。空白標示符就是一個不錯的方式:```goimport _ "image/png"```它甚至在[*image*](https://github.com/golang/go/blob/0104a31b8fbcbe52728a08867b26415d282c35d2/src/image/image.go#L10)包中被提到。如果上面的內容對你有所協助請跟隨我一起續寫未來的故事吧,那也將成為我的動力。---## 參考資料- [The Go Programming Language Specification - The Go Programming Language](https://golang.org/ref/spec#Package_initialization)- [Blocks in Go](https://studygolang.com/articles/12632)- [Initialization dependencies in Go](https://studygolang.com/articles/13158)

via: https://medium.com/golangspec/init-functions-in-go-eac191b3860a

作者:Michał Łowicki 譯者:flexiwind 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

275 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.