golang
中有個神奇的函數init
,該函數會在全部程序執行開始前被調用,每一個包能夠包含多個init
函數,全部被編輯器識別到的init
函數都會在main
函數執行前被調用。一般被用來註冊一個程序須要使用的依賴,如mysql
註冊,配置文件加載等。mysql
package main import "fmt" func main() { fmt.Println("這裏是mian") } func init() { fmt.Println("這裏是Init1") } func init() { fmt.Println("這裏是Init2") } //輸出結果 這裏是Init1 這裏是Init2 這裏是main
一個很簡單的示例,能夠看到init
函數是在main函數執行以前被執行的,而且一個包能夠有多個init
函數golang
package main import ( "fmt" "test/services" ) func main() { fmt.Println("這裏是main") services.Run() } func init() { fmt.Println("這裏是main init") }
package services import "fmt" func Run() { fmt.Println("這裏是 services run") } func init() { fmt.Println("這裏是 services裏面的init") }
這裏是 services裏面的init 這裏是main init 這裏是main 這裏是 services run
能夠看到這裏先執行了services
包裏面的init
,在執行的main
的init
。這是由於在編譯的時候會先去檢查導入的包,首先發現其餘包裏面的init
,而後纔會到main
包裏面的init。那若是services
裏面又包含了其餘的包呢?其餘包裏面又在不一樣的文件中有不的init
呢?下面咱們一塊兒來看看到底init
的順序是怎麼樣的。sql
在上面的基礎上增長third
包編輯器
---services -----service.go ---third -----third_a.go -----third_b.go ---main.go
package third import "fmt" func TestA() { } func init() { fmt.Println("這裏是 third init a") }
package third import "fmt" func TestB() { } func init() { fmt.Println("這裏是 third init b") }
package services import ( "fmt" "test/third" ) func Run() { fmt.Println("這裏是 services run") third.TestB() // 先調用 testB third.TestA() // 在調用 testA } func init() { fmt.Println("這裏是 services裏面的init") }
這裏是 third init a 這裏是 third init b 這裏是 services裏面的init 這裏是 main init 這裏是 main 這裏是 services run
能夠看到這裏先執行了 third_a
中的init
,再執行了third_b
中的init
,而不是按照咱們函數的調用順序來執行的,那麼是按照文件的排序來定的?我以爲應該是這樣的,官方只是說按源文件的順序執行,具體是不是這樣只有靠實際實踐來看,目前來看是這樣的順序。其實咱們大可沒必要糾結太多的順序問題。函數
咱們只須要知道,每一個包中能夠有多個init
函數,而其餘包的init
是在main包的init
調用以前被執行,main
函數最後執行便可,若是非要有依賴的順序關係,那麼能夠在init
中 包含調用便可spa