???💝💝💝歡迎來到我的博客,很高興能夠在這里和您見面!希望您在這里可以感受到一份輕松愉快的氛圍,不僅可以獲得有趣的內容和知識,也可以暢所欲言、分享您的想法和見解。
非常期待和您一起在這個小小的網絡世界里共同探索、學習和成長。💝💝💝 ?? 歡迎訂閱本專欄 ??
?
前言
小鄭最近在準備Go語言的面試題,通過github和b站等各種學習網站上學習go語言的八股文,并且整理出自己覺得面試可能會問到的知識點,希望通過做筆記的方式來鞏固自己的知識點,并且也希望可以幫助到大家在面試的時候更加得心應手一些,那么從現在開始,和我一起加入八股學習之旅吧!
回答重點
逃逸分析是編譯器優化的一部分,用來決定對象應該分配在棧上還是堆上。
在 Go 語言中,編譯器會在編譯期間進行逃逸分析,通過分析代碼中的變量確定它們是否會“逃逸”出當前的作用域。
如果一個變量在函數或方法內被創建,但在函數外部仍然被引用,那么它將被稱為“逃逸”,需要分配到堆上;否則,它將被分配在棧上。
棧分配和堆分配的區別:
棧分配的好處是分配和釋放內存的開銷非常小,速度快。
堆分配需要依賴垃圾回收器(GC)來管理內存,因此開銷相對較大。
逃逸分析的過程
逃逸分析由編譯器在編譯期間進行,它檢查每一個變量的使用情況。編譯器根據變量的作用范圍、生命周期、以及變量是否被傳遞給其他協程或返回到外部等來確定其是否逃逸。
主要的原則包括:
- 若變量的生命周期超出當前函數,則視為逃逸。
- 若變量被引用并存儲到堆上,則視為逃逸。
變量本來應該存在棧上(即是局部的,生命周期只在當前函數內),但是它被引用到堆上,意味著它的生命周期會超出當前函數的作用域,可能會繼續存在下去。這就發生了“逃逸”。
- 若變量被傳遞給外部函數、方法或 goroutine,且存活時間可能超過當前函數,則視為逃逸。
package mainimport "fmt"func escapeExample() *int {x := 42 // 局部變量 xreturn &x // 返回 x 的地址,x 發生逃逸,分配到堆上
}func stackExample() int {x := 42 // 局部變量 xreturn x // x 沒有逃逸,分配在棧上
}
由于 Go 語言的內存模型,如果你將一個局部變量的地址返回,這個變量的生命周期就會被延長。
Go 編譯器會認為 x 的生命周期不能僅限于函數 escapeExample 的作用域,因為返回的地址可能會在函數外部被引用。因此,Go 會把 x 從棧上移動到堆上,并確保它的生命周期持續足夠長。
return x 返回了 x 的值,而不是返回 x 的地址。 在這種情況下,x 的值被復制到了調用者的棧上,這意味著 x 并沒有逃逸到堆上。它依然只在函數內部有效,并且在函數調用結束后會被銷毀。
逃逸分析的優化技巧
返回指針,閉包捕獲,接口賦值,動態類型轉換等會導致變量逃逸。
1,避免不必要的指針返回:如果可能,返回值而不是返回指針。
2,減少閉包對變量的引用:避免在閉包中使用外部變量,盡量將變量傳遞給閉包。
3,游免接口賦值:使用具體類型代營接口,減少逃逸到堆的可能性。
??????小鄭是普通學生水平,如有紕漏,歡迎各位大佬評論批評指正!😄😄😄
💘💘💘如果覺得這篇文對你有幫助的話,也請給個點贊、收藏下吧,非常感謝!👍 👍 👍