最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一篇文章讀懂Golang?init函數(shù)執(zhí)行順序

 更新時(shí)間:2022年11月01日 08:56:20   作者:愛碼大鯉魚  
init()函數(shù)會(huì)在包被初始化后自動(dòng)執(zhí)行,并且在main()函數(shù)之前執(zhí)行,但是需要注意的是init()以及main()函數(shù)都是無法被顯式調(diào)用的,下面這篇文章主要給大家介紹了關(guān)于如何通過一篇文章讀懂Golang?init函數(shù)執(zhí)行順序的相關(guān)資料,需要的朋友可以參考下

1.init 函數(shù)簡介

Golang init 函數(shù)是一種特殊的函數(shù),主要用于完成程序的初始化工作,如初始化數(shù)據(jù)庫的連接、載入本地配置文件、根據(jù)命令行參數(shù)初始化全局變量等。

package main

import "flag"

var gopath string

func init() {
	println("init a")
}

func init() {
	println("init b")
}

func init() {
	println("init c")
	// gopath may be overridden by --gopath flag on command line.
	flag.StringVar(&gopath, "gopath", "/root/go", "override default GOPATH")
}

func main() {
	println("main")
	flag.Parse()
	println(gopath)
}

運(yùn)行輸出:

$ go run main.go --gopath="/home/alice/go"
init a
init b
init c
main
/home/alice/go

之所以特殊,是因?yàn)?init 函數(shù)有如下特點(diǎn):

  • init 函數(shù)是可選的,可以沒有;
  • 與 main 函數(shù)一樣,不能有入?yún)⑴c返回值;
  • 與 main 函數(shù)一樣,init 會(huì)自動(dòng)執(zhí)行,不能被其他函數(shù)調(diào)用;
  • 一個(gè)包內(nèi)可以有多個(gè) init 函數(shù),即可以在包的多個(gè)源文件中定義多個(gè) init 函數(shù)。一般建議在與包同名源文件中寫一個(gè) init 函數(shù),這樣可讀性好且便于維護(hù);
  • 一個(gè)源文件可以有多個(gè) init 函數(shù)。

2.執(zhí)行順序

既然一個(gè)程序可以有多個(gè) init 函數(shù),那么對于位于不同包、不同源文件中的多個(gè) init 函數(shù),其執(zhí)行順序是怎樣的呢?

下面從多個(gè)方面去考察。

2.1 單個(gè)源文件的 init 執(zhí)行順序

package main

func init() {
	println("init a")
}

func init() {
	println("init b")
}

func init() {
	println("init c")
}

func main() {
	println("main")
}

運(yùn)行輸出:

$ go run main.go
init a
init b
init c
main

結(jié)論: 同一個(gè)源文件的 init 函數(shù)執(zhí)行順序與其定義順序一致,從上到下。

2.2 單個(gè)包的 init 執(zhí)行順序

假設(shè) main 包有三個(gè)源文件 a.go,b.go 和 c.go。

// a.go
package main

func init() {
	println("init a")
}

// b.go
package main

func init() {
	println("init b")
}

// c.go
package main

func init() {
	println("init c")
}

// main.go
package main

func init() {
	println("init main")
}

func main() {
	println("main")
}

編譯運(yùn)行輸出:

$ go build && ./main
init a
init b
init c
init main
main

結(jié)論: 同一個(gè)包中不同源文件 init 函數(shù)的執(zhí)行順序,是根據(jù)文件名的字典序來確定。

2.3 main 包導(dǎo)入多個(gè)包時(shí) init 執(zhí)行順序

2.3.1 不存在依賴

對于不同的包,如果不相互依賴的話,在 main 包中被 import,那么這種情況下,各個(gè)包的 init 執(zhí)行順序是怎樣的呢?

假設(shè)有包 a,b 和 c,在 main.go 中被 import。

// a 包
// a.go
package a

func init() {
	println("init a")
}

// b 包
// b.go
package b

func init() {
	println("init b")
}

// c 包
// c.go
package c

func init() {
	println("init c")
}

// main 包
// main.go
package main

import (
	_ "main/a"
	_ "main/b"
	_ "main/c"
)

func init() {
	println("init main")
}

func main() {
	println("main")
}

編譯運(yùn)行輸出:

$ go build && ./main
init a
init b
init c
init main
main

結(jié)論: 對于不同的包,如果不相互依賴的話,按照 main 包中導(dǎo)入順序調(diào)用包的 init 函數(shù),最后再調(diào)用 main 包的 init 函數(shù)。

2.3.2 存在依賴

對于不同的包,如果存在依賴關(guān)系的話,在 main 包中被 import,那么這種情況下,各個(gè)包的 init 執(zhí)行順序是怎樣的呢?

假設(shè)有包 a,b 和 c,main 包 import a 包,a import b,b import c,即依賴關(guān)系為 main > a > b > c。

// a 包
// a.go
package a

import _ "main/b"

func init() {
	println("init a")
}

// b 包
// b.go
package b

import _ "main/c"

func init() {
	println("init b")
}

// c 包
// c.go
package c

func init() {
	println("init c")
}

// main 包
// main.go
package main

import (
	_ "main/a"
)

func init() {
	println("init main")
}

func main() {
	println("main")
}

編譯運(yùn)行輸出:

$ go build && ./main
init c
init b
init a
init main
main

結(jié)論: 如果 package 存在依賴,不同包的 init 函數(shù)按照包導(dǎo)入的依賴關(guān)系決定執(zhí)行順序。 調(diào)用順序?yàn)樽詈蟊灰蕾嚨淖钕缺怀跏蓟?,如?dǎo)入順序 main > a > b > c,則初始化順序?yàn)?c > b > a > main,依次執(zhí)行對應(yīng)的 init 方法。

2.4 包級變量初始化與 init 函數(shù)執(zhí)行順序

如果包中存在包級變量,那么其初始化與 init 函數(shù)執(zhí)行先后順序如何呢?

還是假設(shè)有包 a,b 和 c,main 包 import a 包,a import b,b import c,即依賴關(guān)系為 main > a > b > c。且每個(gè)包都有一個(gè)包級變量,并通過函數(shù)完成其初始化。

// a 包
// a.go
package a

import _ "main/b"

var A = func() string {
	println("init var A")
	return "A"
}()

func init() {
	println("init a")
}

// b 包
// b.go
package b

import _ "main/c"

var B = func() string {
	println("init var B")
	return "B"
}()

func init() {
	println("init b")
}

// c 包
// c.go
package c

var C = func() string {
	println("init var C")
	return "C"
}()

func init() {
	println("init c")
}

// main 包
// main.go
package main

import (
	_ "main/a"
)

var m = func() string {
	println("init var m")
	return "m"
}()

func init() {
	println("init main")
}

func main() {
	println("main")
}

編譯運(yùn)行輸出:

$ go build && ./main
init var C
init c
init var B
init b
init var A
init a
init var m
init main
main

結(jié)論: 可見每個(gè)包的包級變量初始化是在 init 函數(shù)執(zhí)行之前完成的。不同包的 init 函數(shù)與包級變量的初始化順序如下圖所示。

3.小結(jié)

Golang 中的 init 是一種特殊的函數(shù),主要用于完成程序的初始化工作。其特點(diǎn)有:

  • init 函數(shù)是可選的,可以沒有;
  • 與 main 函數(shù)一樣,不能有入?yún)⑴c返回值;
  • 與 main 函數(shù)一樣,init 會(huì)自動(dòng)執(zhí)行,不能被其他函數(shù)調(diào)用;
  • 一個(gè)包內(nèi)可以有多個(gè) init 函數(shù),即可以在包的多個(gè)源文件中定義多個(gè) init 函數(shù)。一般建議在與包同名源文件中寫一個(gè) init 函數(shù),這樣可讀性好且便于維護(hù);
  • 一個(gè)源文件可以有多個(gè) init 函數(shù)。

程序中如果在不同包的不同源文件有多個(gè) init 函數(shù)時(shí),其執(zhí)行順序可概述為:

  • 同一個(gè)源文件的 init 函數(shù)執(zhí)行順序與其定義順序一致,從上到下;
  • 同一個(gè)包中不同文件的 init 函數(shù)的執(zhí)行順序按照文件名的字典序;
  • 對于不同的包,如果不相互依賴的話,按照 main 包中 import 的順序調(diào)用其包中的 init 函數(shù);
  • 如果包存在依賴,不同包的 init 函數(shù)按照包導(dǎo)入的依賴關(guān)系決定執(zhí)行順序。 調(diào)用順序?yàn)樽詈蟊灰蕾嚨淖钕缺怀跏蓟?,如?dǎo)入順序 main > a > b > c,則初始化順序?yàn)?c > b > a > main,依次執(zhí)行對應(yīng)的 init 方法;
  • 如果包存在包級變量,則先于包的 init 函數(shù)完成初始化。

程序的初始化和執(zhí)行都起始于 main 包。如果 main 包還導(dǎo)入了其它的包,那么就會(huì)在編譯時(shí)將它們依次導(dǎo)入。有時(shí)一個(gè)包會(huì)被多個(gè)包同時(shí)導(dǎo)入,那么它只會(huì)被導(dǎo)入一次(例如很多包可能都會(huì)用到 fmt 包,但它只會(huì)被導(dǎo)入一次,因?yàn)闆]有必要導(dǎo)入多次)。

當(dāng)一個(gè)包被導(dǎo)入時(shí),如果該包還導(dǎo)入了其它的包,那么會(huì)先將其它包導(dǎo)入進(jìn)來,然后再對這些包中的包級常量和變量進(jìn)行初始化,接著執(zhí)行 init 函數(shù),依次類推。

請務(wù)必銘記于心,雖然 init() 順序是明確的,但代碼可以更改,init() 函數(shù)之間的關(guān)系可能會(huì)使代碼變得脆弱和容易出錯(cuò),因此在編碼時(shí)避免依賴 init() 函數(shù)的執(zhí)行順序。

參考文獻(xiàn)

總結(jié) 

到此這篇關(guān)于一篇文章讀懂Golang init函數(shù)執(zhí)行順序的文章就介紹到這了,更多相關(guān)Golang init函數(shù)執(zhí)行順序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言Gin處理響應(yīng)方式詳解

    Go語言Gin處理響應(yīng)方式詳解

    gin框架封裝了常用的數(shù)據(jù)格式方法響應(yīng)于客戶端,下面這篇文章主要給大家介紹了關(guān)于Go語言Gin處理響應(yīng)方式的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • golang生成JSON以及解析JSON

    golang生成JSON以及解析JSON

    這篇文章主要介紹了golang生成JSON以及解析JSON,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • go語言日志記錄庫簡單使用方法實(shí)例分析

    go語言日志記錄庫簡單使用方法實(shí)例分析

    這篇文章主要介紹了go語言日志記錄庫簡單使用方法,實(shí)例分析了Go語言日志記錄的操作的技巧,需要的朋友可以參考下
    2015-03-03
  • Golang?websocket協(xié)議使用淺析

    Golang?websocket協(xié)議使用淺析

    這篇文章主要介紹了Golang?websocket協(xié)議的使用,WebSocket是一種新型的網(wǎng)絡(luò)通信協(xié)議,可以在Web應(yīng)用程序中實(shí)現(xiàn)雙向通信,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • 淺析Go語言容器之?dāng)?shù)組和切片的使用

    淺析Go語言容器之?dāng)?shù)組和切片的使用

    在?Java?的核心庫中,集合框架可謂鼎鼎大名:Array?、List、Set等等,隨便拎一個(gè)出來都值得開發(fā)者好好學(xué)習(xí)如何使用甚至是背后的設(shè)計(jì)源碼。雖然Go語言沒有如此豐富的容器類型,但也有一些基本的容器供開發(fā)者使用,接下來讓我們認(rèn)識(shí)一下這些容器類型吧
    2022-11-11
  • golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹

    golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹

    這篇文章主要介紹了golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang中map縮容的實(shí)現(xiàn)

    Golang中map縮容的實(shí)現(xiàn)

    本文主要介紹了Go語言中map的擴(kuò)縮容機(jī)制,包括grow和hashGrow方法的處理,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • 使用Go語言簡單模擬Python的生成器

    使用Go語言簡單模擬Python的生成器

    這篇文章主要介紹了使用Go語言簡單模擬Python的生成器,Python的generator是非常酷的功能,用Go實(shí)現(xiàn)的代碼也較為簡潔,需要的朋友可以參考下
    2015-08-08
  • Go語言拼接URL路徑的三種方法

    Go語言拼接URL路徑的三種方法

    本文主要介紹了Go語言拼接URL路徑的三種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Golang?動(dòng)態(tài)腳本調(diào)研詳解

    Golang?動(dòng)態(tài)腳本調(diào)研詳解

    這篇文章主要為大家介紹了Golang?動(dòng)態(tài)腳本調(diào)研詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論

灵川县| 德江县| 响水县| 长白| 佛冈县| 柏乡县| 大埔县| 南乐县| 灵璧县| 阳东县| 大田县| 揭东县| 台山市| 涟源市| 新兴县| 富锦市| 玉山县| 泌阳县| 邵阳市| 修武县| 宣汉县| 大关县| 廉江市| 玉田县| 图片| 渭源县| 中西区| 元谋县| 德江县| 乌拉特后旗| 通海县| 乐山市| 平远县| 泾源县| 博湖县| 吉隆县| 南和县| 南昌市| 灵石县| 临夏市| 南木林县|