Golang中逃逸現象, 變量“何時棧?何時堆?”

目錄

什么是棧

什么是堆

棧 vs 堆(核心區別)

GO編譯器的逃逸分析

什么是逃逸分析?

怎么看逃逸分析結果?

典型“會逃逸”的場景

閉包捕獲局部變量

返回或保存帶有“底層存儲”的容器

經由接口/反射/fmt 等導致裝箱或被長期保存

把指針/引用存入全局、堆對象或長生命周期結構

???????參數“內容”被函數保留(編譯器推不動)

GO中的“堆/棧”怎么落地

落地

是否上堆由逃逸分析決定

什么時候“應該”用誰?


什么是棧

是每個線程私有、按先進后出管理的調用臨時區。

什么是堆

是進程共享、由內存分配器/GC統一管理的動態內存區。

棧 vs 堆(核心區別)

  • 歸屬:棧是“每個線程一個棧”;堆是“整個進程(多線程)共享一大片內存”

  • 用途:棧放調用過程相關的數據(返回地址、保存寄存器、局部變量等);堆放動態創建、可跨函數/長期存在的數據

  • 生命周期:棧隨函數返回自動回收(棧幀彈出);堆由程序(free/delete)或垃圾回收器回收

  • 分配/釋放成本:棧是簡單的指針移動,極快;堆需要向分配器申請/釋放,相對慢

  • 訪問局部性:棧一般連續,緩存友好;堆可能碎片化

  • 常見錯誤:棧——遞歸太深/局部數組過大導致棧溢出;堆——內存泄漏/重用已釋放內存/碎片

  • 大小:棧通常較小且固定/可增長(按語言/平臺而定);堆通常大很多(由 OS/運行時管理)

GO編譯器的逃逸分析

go語言編譯器會自動決定把一個變量放在棧還是放在堆,編譯器會做逃逸分析(escape analysis)當發現變量的作用域沒有跑出函數范圍,就可以在棧上,反之則必須分配在堆。 go語言聲稱這樣可以釋放程序員關于內存的使用限制,更多的讓程序員關注于程序功能邏輯本身。

什么是逃逸分析?

編譯器在編譯期判斷一個變量是否會在當前函數返回后仍被引用(“逃出”當前棧幀)。

  • 不逃逸 → 盡量放在上,分配/回收極快;

  • 逃逸 → 放到上,由運行時/GC 管理,帶來分配與 GC 成本。

怎么看逃逸分析結果?

在你的包目錄運行(推薦關掉內聯更好讀):

go build -gcflags='all=-m -l' ./...
# 或者對測試/基準:
go test  -run=^$ -bench=. -gcflags='all=-m -l' ./...

常見輸出含義:

  • moved to heap: x / escapes to heap:變量 x 上堆了

  • does not escape:未逃逸(可棧上)

  • leaking param / leaking param content:把參數或其內容泄露到了可能長壽命的位置(導致逃逸)

典型“會逃逸”的場景

返回局部變量的地址/引用

func f1() *int {x := 10return &x // x 逃逸:必須活到函數返回之后
}

閉包捕獲局部變量

func f2() func() {x := 0return func() { x++ } // x 被閉包捕獲 → 逃逸
}

返回或保存帶有“底層存儲”的容器

func f3(n int) []int {s := make([]int, n)return s // s 的底層數組需在返回后仍然存活 → 逃逸
}

經由接口/反射/fmt 等導致裝箱或被長期保存

func f4(b []byte) {_ = fmt.Sprintf("%x", b) // b 常見會逃逸(fmt 可變參、接口裝箱)
}

???????把指針/引用存入全局、堆對象或長生命周期結構

var g []*T
func f5(p *T) {g = append(g, p) // p 的“內容”被長期保存 → 逃逸
}

???????參數“內容”被函數保留(編譯器推不動)

func keepPtr(pp **int) { stash = *pp } // 比如存到包級變量
func caller() {x := 1p := &xkeepPtr(&p) // 報 "leaking param content: p"
}

GO中的“堆/棧”怎么落地

落地

  • 語法上沒有顯式“棧/堆”關鍵字;逃逸分析決定變量放棧還是堆

  • 一般規律:不逃逸的局部數據可在棧上;返回到函數外/被閉包捕獲等會逃逸到堆

  • make(slice/map/channel)和 new 只是創建方式,是否上堆由逃逸分析決定,堆內存由 GC 回收

是否上堆由逃逸分析決定

type T struct { buf [1024]byte }func f() *T {t := T{}   // 語義上是局部變量;若返回其地址 => 逃逸到堆(由編譯器決定)return &t
}func g() {t := T{}   // 不逃逸的話,可能在棧上分配,函數返回就回收_ = t
}

什么時候“應該”用誰?

  • 短生命周期、只在當前調用鏈內使用:棧(語言通常自動用棧)

  • 需要跨函數/跨協程/長期緩存:堆(動態分配)

  • 在擁有 GC 的語言(Go/Java/Python)中,寫法更關注語義,由編譯器/運行時決定最終放棧還是堆;只需要留意可能引發逃逸的用法和不必要的大對象分配。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95661.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95661.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95661.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL入門指南:從安裝到工作原理

什么是MySQL MySQL是一個開源的關系型數據庫管理系統,由瑞典MySQL AB公司開發(目前屬于Oracle公司),被廣泛地應用在大中小型網站中 MySQL是一個小型的開源的關系型數據庫管理系統,與其他大型數據庫管理系統例如&…

dask.dataframe.shuffle.set_index中獲取 divisions 的步驟分析

dask.dataframe.shuffle.set_index 中獲取 divisions 的步驟分析 主要流程概述 在 set_index 函數中,當 divisionsNone 時,系統需要通過分析數據來動態計算分區邊界。這個過程分為以下幾個關鍵步驟: 1. 初始檢查和準備 if divisions is None:…

ai生成ppt工具有哪些?10款主流AI生成PPT工具盤點

隨著人工智能技術的飛速發展,AI生成PPT工具逐漸成為職場人士、學生和創作者提升效率的得力助手。這類工具通過智能算法,能夠快速將文本、數據或創意轉化為結構化、視覺化的演示文稿,大幅節省設計時間。1、AiPPT星級評分:★★★★★…

Qt多線程編程學習

Qt多線程編程學習 1. 項目概述 本項目展示了Qt中多線程編程的基本用法,通過繼承QThread類創建自定義線程,并演示了線程的啟動、執行和銷毀過程。項目包含一個簡單的用戶界面,用戶可以通過按鈕控制線程的啟動和結束。 1.1 項目結構 項目包含以…

加密貨幣武器化:惡意npm包利用以太坊智能合約實現隱蔽通信

ReversingLabs研究人員發現兩個惡意npm包利用以太坊(Ethereum)智能合約隱藏并傳播惡意軟件。這兩個名為colortoolsv2和mimelib2的軟件包于2025年7月被識別,展現了開源安全攻防戰中的新戰術。惡意軟件包偽裝成實用工具攻擊活動始于7月7日發布的…

Spring Boot 全局字段處理最佳實踐

在日常開發中,我們總會遇到一些瑣碎但又無處不在的字段處理需求:? 請求處理: 用戶提交的表單,字符串前后帶了多余的空格,需要手動 trim()。? 響應處理: 返回給前端的 BigDecimal 金額,因為精度問題導致JS處理出錯&am…

三坐標測量機在汽車制造行業中的應用

在汽車制造業中,零部件精度決定著整車性能。從發動機活塞的微米級公差,到車身焊接的毫米級間隙,汽車制造“差之毫厘,謬以千里” ,任何細微偏差都可能引發連鎖反應:發動機抖動、異響、油耗飆升,車…

機床夾具設計 +選型

機床夾具設計—第2組(鉆床夾具)仿真組裝視頻_嗶哩嗶哩_bilibili 夾具-商品搜索-怡合達一站式采購平臺 米思米FA標準品電子目錄new 可能要吧這些定位塊單獨用yolo訓練一邊才能搞識別分析 3長條一短銷定位,黃色的用來夾緊 一個面加一短軸一棱…

表格識別技術:通過計算機視覺和OCR,實現非結構化表格向結構化數據的轉換,推動數字化轉型。

在日常工作和生活中,我們無處不在與表格打交道。從財務報表、發票收據,到科研論文中的數據表、醫療報告,表格以其清晰、結構化的方式,承載著大量關鍵信息。然而,當這些表格以紙質或圖片等非結構化形式存在時&#xff0…

Go基礎(②Viper)

Viper 讀取配置創建一個配置文件 config.yamlserver:port: 8080timeout: 30 # 超時時間(秒) database:host: "localhost"user: "root"password: "123456"name: "mydb"然后用 Viper 讀取這個配置,代…

kafka Partition(分區)詳解

一、什么是 PartitionPartition(分區) 是 Kafka Topic(主題) 的最小并行單位。一個 Topic 可以包含多個 Partition,每個 Partition 底層對應一個有序、不可變的消息隊列,消息只會順序追加。Partition 內部消…

中創中間件適配HGDB

文章目錄環境文檔用途詳細信息環境 系統平臺:Microsoft Windows (64-bit) 10 版本:5.6.5 文檔用途 本文章主要介紹中創中間件簡單適配HGDB。 詳細信息 一、數據源配置 1.數據庫準備 (1)安裝HGDB并創建一個名為myhgdb的數據…

服務器內存和普通計算機內存在技術方面有什么區別?

服務器內存和普通計算機內存在技術上的區別,主要體現在為滿足不同工作場景和要求而采用的設計和特性上。下面這個表格匯總了它們的主要技術差異,方便你快速了解: ?技術特性??服務器內存??普通計算機內存??錯誤校驗 (ECC)??支持ECC(…

哪款AI生成PPT工具對職場新人最友好?操作門檻最低的是哪個?

一句話生成專業PPT,職場新人也能輕松做出高質量演示文稿現代職場節奏快,PPT制作已成為必備技能。然而,職場新人常面臨兩大挑戰:缺乏設計經驗,以及需要在有限時間內完成高質量演示。傳統PPT制作耗時費力,需梳…

1.注解的力量:Spring Boot如何用注解重構IoC容器

文章目錄1.1 IoC容器:Spring的智能管家1.2 注解驅動:給管家下指令1.2.1 SpringBootApplication:總管家的聘書1.2.2 組件注解:員工的身份標識1.2.3 Autowired:依賴注入的三種方式1.2.4 Bean注解:手動招聘特殊…

【算法】92.翻轉鏈表Ⅱ--通俗講解

一、題目是啥?一句話說清 給你一個鏈表和兩個整數 left 和 right,反轉從第 left 個節點到第 right 個節點的子鏈表,并返回反轉后的鏈表。其他部分保持不變。 示例: 輸入:head = [1,2,3,4,5], left = 2, right = 4 輸出:[1,4,3,2,5](反轉了從第2到第4個節點) 二、解題…

Nature子刊:新發現!深層腦網絡中發現強迫癥癥狀的神經生物標志物

強迫癥(OCD)是一種令人困擾的精神疾病,患者常常被強迫思維和強迫行為所困擾。例如,有些人會反復洗手,無法控制自己的清潔沖動;還有些人會不斷檢查門窗是否關好,即便他們已經確認過無數次。這些行…

Onlyoffice集成與AI交互操作指引(Iframe版)

Onlyoffice集成與AI交互操作指引(Iframe版) 本文檔系統介紹了軟件系統集成OnlyOffice實現在線編輯與AI輔助功能的方案。主要內容包括:后端需提供文檔配置信息并實現Callback接口以處理文檔保存;前端通過Vue集成編輯器&#xff0c…

TypeScript 中 keyof、typeof 和 instanceof

在 TypeScript 開發中,keyof、typeof 和 instanceof 是核心的類型操作符和操作符,專門用于提升類型安全、代碼可讀性和維護性。1. keyof 操作符定義和用途:keyof 是一個類型操作符,用于獲取對象類型的所有鍵(屬性名&am…

分布式專題——1.1 Redis單機、主從、哨兵、集群部署

1 Redis 部署 下面演示在 Linux 環境下部署 Redis7。 1.1 單機部署 1.1.1 檢查安裝 gcc 環境Redis 是由 C 語言編寫的,它的運行需要 C 環境,因此我們需要先安裝 gcc; # 關閉防?墻 systemctl stop firewalld.service # 查看防火墻狀態 firewa…