深入理解Go語言init方法的執(zhí)行順序
一、什么是init方法?
init 是 Go 語言中的特殊函數,無需手動調用,由運行時自動執(zhí)行。每個 .go 文件可以包含多個 init 函數。init方法沒有參數和返回值。
示例代碼如下:
func init() {
// 初始化邏輯
}init 函數在 main() 函數之前執(zhí)行。當包被導入時,系統(tǒng)會自動調用所有 init 函數,其調用順序為:先執(zhí)行依賴包(被導入的包)的 init 函數,再執(zhí)行當前包的 init 函數,最后執(zhí)行 main() 函數。
二、init方法特性
1)執(zhí)行順序規(guī)則
(1)同一個文件多個init方法執(zhí)行順序
同一文件內的 init 函數則按照代碼編寫順序執(zhí)行,代碼示例如下:
var config string
func init() {
config = "config1"
fmt.Println("init 1:", config)
}
func init() {
fmt.Println("init 2: additional setup")
}
func main() {
fmt.Println("main:", config)
}執(zhí)行結果如下:

(2)同一個包內執(zhí)行順序
同一包內的文件會按照文件名進行字典序排序,并按此順序執(zhí)行各文件中的 init 函數。如包內包括a.go和b.go兩個文件,優(yōu)先執(zhí)行a.go中的init方法,在執(zhí)行b.go中的init方法。
代碼示例如下:
// a.go
package main
import "fmt"
func init() {
fmt.Println("a.go init")
}
// b.go
package main
import "fmt"
func init() {
fmt.Println("b.go init")
}
// main.go
package main
import "fmt"
func init() {
fmt.Println("main init")
}
func main() {
fmt.Println("main")
}運行結果如下:

(3)跨包執(zhí)行順序
對于跨包依賴的情況,遵循"深度優(yōu)先"原則,即最后被依賴的包會最先完成初始化。例如在 main → A → B → C 的依賴鏈中,初始化順序為 C → B → A → main。
代碼包結構如下:

代碼示例如下:
// a.go
package A
import (
"fmt"
"te/src/B"
)
func init() {
fmt.Println("a.go init")
}
func PrintA() {
fmt.Println("print a")
B.PrintB()
}
// b.go
package B
import (
"fmt"
"te/src/C"
)
func init() {
fmt.Println("b.go init")
}
func PrintB() {
fmt.Println("print b")
C.PrintC()
}
// c.go
package C
import "fmt"
func init() {
fmt.Println("c.go init")
}
func PrintC() {
fmt.Println("print c")
}
// main.go
package main
import (
"fmt"
"te/src/A"
)
func init() {
fmt.Println("main init")
}
func main() {
fmt.Println("main")
A.PrintA()
}執(zhí)行結果如下:

2)與變量初始化的關系
包級變量初始化優(yōu)先于 init 執(zhí)行。示例代碼如下:
// 先執(zhí)行
var config = initConfig()
func initConfig() string {
fmt.Println("initConfig")
return "initConfig"
}
// 后執(zhí)行
func init() {
config = "init"
fmt.Println("init()", config)
}
func main() {
fmt.Println(config)
}運行結果如下:

三、init應用場景
| 場景 | 用途說明 |
|---|---|
| 全局變量初始化 | 復雜配置加載,如數據庫連接池設置 |
| 驅動/插件注冊 | 數據庫驅動注冊 |
| 副作用代碼執(zhí)行 | 日志系統(tǒng)初始化,如設設置日志級別和輸出格式 |
| 確保初始化順序 | 依賴資源預加載,如配置文件讀取優(yōu)先于服務啟動 |
四、init使用注意事項
1)避免濫用:過度使用 init 函數會降低代碼可讀性,建議采用顯式初始化方式。對于復雜邏輯,應封裝為普通函數并在 main 中顯式調用。
2)線程安全:所有 init 函數都在同一個 goroutine 中執(zhí)行,因此無需加鎖。
3)初始化方法應僅包含不會失敗的操作 。
到此這篇關于深入理解Go語言init方法的執(zhí)行順序的文章就介紹到這了,更多相關Go語言init執(zhí)行順序內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go?for-range?的?value值地址每次都一樣的原因解析
循環(huán)語句是一種常用的控制結構,在?Go?語言中,除了?for?關鍵字以外,還有一個?range?關鍵字,可以使用?for-range?循環(huán)迭代數組、切片、字符串、map?和?channel?這些數據類型,這篇文章主要介紹了Go?for-range?的?value值地址每次都一樣的原因解析,需要的朋友可以參考下2023-05-05
golang提示dial?tcp?172?.217.163.49:443:?connectex:?A?con
這篇文章主要為大家介紹了golang提示dial?tcp?172?.217.163.49:443:?connectex:?A?connection?attempt?failed解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
基于gin的golang web開發(fā)之認證利器jwt
這篇文章主要介紹了基于gin的golang web開發(fā)之認證利器jwt,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
Goland調節(jié)字體大小的設置(編輯區(qū),terminal區(qū),頁面字體)
這篇文章主要介紹了Goland調節(jié)字體大小的設置(編輯區(qū),terminal區(qū),頁面字體),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

