欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GO中什么情況會(huì)使用變量逃逸

 更新時(shí)間:2023年02月14日 10:19:59   作者:阿兵云原生  
本文主要介紹了GO中什么情況會(huì)使用變量逃逸,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

你知道 GO 中什么情況會(huì)變量逃逸嗎?首先我們先來(lái)看看什么是變量逃逸

Go 語(yǔ)言將這個(gè)以前我們寫 C/C++ 時(shí)候需要做的內(nèi)存規(guī)劃和分配,全部整合到了 GO 的編譯器中,GO 中將這個(gè)稱為 變量逃逸

GO 通過(guò)編譯器分析代碼的特征和代碼的生命周期,決定應(yīng)該使用堆還是棧來(lái)進(jìn)行內(nèi)存分配

C 代碼 和 GO 代碼對(duì)比哪個(gè)會(huì)崩潰?

咱們寫一個(gè)簡(jiǎn)單的例子,在 C 里面內(nèi)存分配到棧上面還是堆上面是一個(gè)很明確的事情

例如

函數(shù)中的變量是分配在棧上面,會(huì)隨著該函數(shù)調(diào)用完畢后隨之銷毀掉

程序員自己 malloc 開辟的內(nèi)存是在堆上面,需要程序員自己去釋放

那么問題來(lái)了:

如果我們將某一個(gè)函數(shù)中的局部變量的地址(全篇以局部變量為例),作為該函數(shù)的返回值,最終在函數(shù)外部去訪問這個(gè)局部變量的地址,是否會(huì)出錯(cuò)呢?一起來(lái)看看吧

C 程序

test.c

int * get_res(int num){
    int tmp = num + 10;
    return &tmp;
}

int main(){
    int * res = get_res(80);
    printf("%d  -- %p\n" , *res, res);
}

上面寫了一個(gè)簡(jiǎn)單的 C 代碼,獲取傳入數(shù)據(jù)并 + 10 得到的結(jié)果

# gcc test.c  -o test
test.c: In function ‘get_res':
test.c:7:12: warning: function returns address of local variable [-Wreturn-local-addr]
     return &tmp;
            ^~~~
# ./test
Segmentation fault

這里可以看出編譯程序,報(bào)了 warning 了,不過(guò)不影響程序的編譯 , 這個(gè) warning 報(bào)錯(cuò)信息是 因?yàn)槲覀兎祷亓伺R時(shí)變量的地址,C 編譯器檢測(cè)到了,給我們拋出了一個(gè) warning

執(zhí)行編譯的程序后,崩潰了 , 熟悉 C 的小伙伴一點(diǎn)都不驚慌,他們不會(huì)寫出這種代碼

出現(xiàn) 段錯(cuò)誤 的原因很明顯,上面有說(shuō)到,是因?yàn)橥獠吭L問了局部變量的地址,外部訪問的時(shí)候,此時(shí)這個(gè)局部變量已經(jīng)被銷毀了,此時(shí)外部訪問的這個(gè)指針,屬于野指針,因此出現(xiàn)程序崩潰

GO 程序

go 程序的邏輯和上面 C 程序的邏輯一模一樣,那么我們看看是否會(huì)出現(xiàn)程序崩潰呢

func getRes(num int) *int {
	tmp := num + 10
	return &tmp
}
func main() {
	res := getRes(80)
	fmt.Printf("%d  -- %p\n", *res, res)
}

執(zhí)行上述代碼,查看效果

# go run main.go
90  -- 0xc420018078

熟悉 go 語(yǔ)言的 小伙伴看到這里心中也毫無(wú)波瀾,程序正常執(zhí)行,沒有崩潰,因?yàn)樗麄冎涝?,這個(gè)現(xiàn)象屬于 變量逃逸

那么我們一起來(lái)看看 GO 為什么會(huì)這樣做,是如何做的呢?

GO 的逃逸是啥樣子的?

上面有說(shuō)到 GO 不會(huì)像 C/C++ 一樣需要程序員自己去關(guān)心內(nèi)存分配,是期望 GO 程序員更多的關(guān)注邏輯

因此內(nèi)存分配這一塊,GO 編譯器都做的妥妥的,一個(gè)變量是分配在棧上面還是堆上面,不是簡(jiǎn)單的看一個(gè)變量是局部變量就分配到棧上,這個(gè)是根據(jù)具體的使用的,有時(shí)候它也會(huì)被分配到堆上面

當(dāng)我們發(fā)現(xiàn)本應(yīng)該分配在棧上面的變量,卻分配在堆上面了,說(shuō)明發(fā)生了逃逸

開始探究和驗(yàn)證

我們可以嘗試寫一個(gè)簡(jiǎn)單的 demo ,還是將局部變量的地址返回到外部去,外部來(lái)訪問這個(gè)局部變量的地址

func getRes(tmp int) *int {

	var t1 int = 1
	var t2 int = 2
	var t3 int = 3

	println(&tmp, &t1, &t2, &t3)

	return &t2
}

func main() {
	res := getRes(80)
	println(*res, res)
}

執(zhí)行上述代碼查看效果

# go run main.go
0xc420045f50 0xc420045f68 0xc420045f60 0xc420045f58
2 0xc420045f60

通過(guò)上面的將變量地址打印出來(lái)貌似沒有看出上面端倪,地址是也是連續(xù)的

那么我們使用 go 提供的工具來(lái)看看這個(gè)程序是不是存在逃逸

執(zhí)行 # go tool compile -m main.go 查看效果如下

main.go:11:9: &t2 escapes to heap
main.go:6:6: moved to heap: t2

go tool compile 工具很明顯的調(diào)試出來(lái)說(shuō)明 t2 這個(gè)變量已經(jīng)逃逸到 堆上面去了

感興趣的話還可以利用工具瞅一眼匯編,多了解一點(diǎn)也有好處

剛才參數(shù) -m 是直接查看是否逃逸,我們可以加 -S 會(huì)打印出具體的會(huì)變代碼,查看該變量是否是 new 出來(lái)的

# go tool compile -S main.go | grep new
0x0035 00053 (main.go:6)        CALL    runtime.newobject(SB)
rel 54+4 t=8 runtime.newobject+0

對(duì)應(yīng)的看看代碼,就是 創(chuàng)建 t2 變量的這一行

對(duì)于 go tool compile 工具,我們可以通過(guò) help 命令來(lái)查看一下

# go tool compile --help

到此這篇關(guān)于GO中什么情況會(huì)使用變量逃逸的文章就介紹到這了,更多相關(guān)GO 變量逃逸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

  • Go語(yǔ)言net包RPC遠(yuǎn)程調(diào)用三種方式http與json-rpc及tcp

    Go語(yǔ)言net包RPC遠(yuǎn)程調(diào)用三種方式http與json-rpc及tcp

    這篇文章主要為大家介紹了Go語(yǔ)言net包RPC遠(yuǎn)程調(diào)用三種方式分別使用http與json-rpc及tcp的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • go實(shí)現(xiàn)冒泡排序算法

    go實(shí)現(xiàn)冒泡排序算法

    冒泡排序算法是數(shù)據(jù)結(jié)構(gòu)中常用的一種算法,本文就介紹了go實(shí)現(xiàn)冒泡排序算法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Go 語(yǔ)言中的 http.FileSystem詳細(xì)解析

    Go 語(yǔ)言中的 http.FileSystem詳細(xì)解析

    在本文中,我們深入探討了 Go 語(yǔ)言中的 http.FileSystem 接口,并介紹了它的基本原理、使用方法以及實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Go語(yǔ)言基礎(chǔ)數(shù)組用法及示例詳解

    Go語(yǔ)言基礎(chǔ)數(shù)組用法及示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)Go語(yǔ)言數(shù)組的用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11
  • Go?語(yǔ)言入門之Go?計(jì)時(shí)器介紹

    Go?語(yǔ)言入門之Go?計(jì)時(shí)器介紹

    這篇文章主要介紹了Go?語(yǔ)言入門之Go?計(jì)時(shí)器,文章基于GO語(yǔ)言的相關(guān)資料展開對(duì)其中計(jì)時(shí)器的詳細(xì)內(nèi)容。具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • golang實(shí)現(xiàn)并發(fā)控制的方法和技巧

    golang實(shí)現(xiàn)并發(fā)控制的方法和技巧

    golang 是一門支持并發(fā)的編程語(yǔ)言,它提供了 goroutine 和 channel 等強(qiáng)大的特性,讓我們可以輕松地創(chuàng)建和管理多個(gè)執(zhí)行單元,實(shí)現(xiàn)高效的任務(wù)處理,在本文中,我們將介紹一些 golang 的并發(fā)控制的方法和技巧,希望對(duì)你有所幫助
    2024-03-03
  • golang實(shí)現(xiàn)簡(jiǎn)單工廠、方法工廠、抽象工廠三種設(shè)計(jì)模式

    golang實(shí)現(xiàn)簡(jiǎn)單工廠、方法工廠、抽象工廠三種設(shè)計(jì)模式

    這篇文章介紹了golang實(shí)現(xiàn)簡(jiǎn)單工廠、方法工廠、抽象工廠三種設(shè)計(jì)模式的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • go如何使用gin結(jié)合jwt做登錄功能簡(jiǎn)單示例

    go如何使用gin結(jié)合jwt做登錄功能簡(jiǎn)單示例

    jwt全稱Json web token,是一種認(rèn)證和信息交流的工具,這篇文章主要給大家介紹了關(guān)于go如何使用gin結(jié)合jwt做登錄功能的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 一文詳解Golang的模塊版本管理與語(yǔ)義版本控制

    一文詳解Golang的模塊版本管理與語(yǔ)義版本控制

    在Golang中,模塊(module)是Go 1.11版本引入的依賴管理系統(tǒng),幫助開發(fā)者管理項(xiàng)目的依賴,在Go模塊推出之前,開發(fā)者通常使用GOPATH和vendor目錄來(lái)管理項(xiàng)目的依賴,本文將給大家詳細(xì)介紹Golang的模塊版本管理與語(yǔ)義版本控制,需要的朋友可以參考下
    2023-12-12
  • 最新評(píng)論