### **知道golang的內存逃逸嗎?什么情況下會發生內存逃逸?**
`golang程序變量`會攜帶有一組校驗數據,用來證明它的整個生命周期是否在運行時完全可知。如果變量通過了這些校驗,它就可以在`棧上`分配。否則就說它`逃逸`了,必須在`堆上分配`。
能引起變量逃逸到堆上的**典型情況**:
* **在方法內把局部變量指針返回**局部變量原本應該在棧中分配,在棧中回收。但是由于返回時被外部引用,因此其生命周期大于棧,則溢出。
* **發送指針或帶有指針的值到 channel 中。**在編譯時,是沒有辦法知道哪個 goroutine 會在 channel 上接收數據。所以編譯器沒法知道變量什么時候才會被釋放。
* **在一個切片上存儲指針或帶指針的值。**一個典型的例子就是 \[\]\*string 。這會導致切片的內容逃逸。盡管其后面的數組可能是在棧上分配的,但其引用的值一定是在堆上。
* **slice 的背后數組被重新分配了,因為 append 時可能會超出其容量( cap )。**slice 初始化的地方在編譯時是可以知道的,它最開始會在棧上分配。如果切片背后的存儲要基于運行時的數據進行擴充,就會在堆上分配。
* **在 interface 類型上調用方法。**在 interface 類型上調用方法都是動態調度的 —— 方法的真正實現只能在運行時知道。想像一個 io.Reader 類型的變量 r , 調用 r.Read(b) 會使得 r 的值和切片b 的背后存儲都逃逸掉,所以會在堆上分配。
命令:go build -gcflags=-m main.go
在Go語言中,開發者模糊了棧區與堆區的差別,不管是字符串、數組字面量,還是通過new、make標識符創建的對象,都既可能被分配到棧中,也可能被分配到堆中。分配時,遵循以下兩個原則:
◎ 原則1:指向棧上對象的指針不能被存儲到堆中
◎ 原則2:指向棧上對象的指針不能超過該棧對象的生命周期
- Go準備工作
- 依賴管理
- Go基礎
- 1、變量和常量
- 2、基本數據類型
- 3、運算符
- 4、流程控制
- 5、數組
- 數組聲明和初始化
- 遍歷
- 數組是值類型
- 6、切片
- 定義
- slice其他內容
- 7、map
- 8、函數
- 函數基礎
- 函數進階
- 9、指針
- 10、結構體
- 類型別名和自定義類型
- 結構體
- 11、接口
- 12、反射
- 13、并發
- 14、網絡編程
- 15、單元測試
- Go常用庫/包
- Context
- time
- strings/strconv
- file
- http
- Go常用第三方包
- Go優化
- Go問題排查
- Go框架
- 基礎知識點的思考
- 面試題
- 八股文
- 操作系統
- 整理一份資料
- interface
- array
- slice
- map
- MUTEX
- RWMUTEX
- Channel
- waitGroup
- context
- reflect
- gc
- GMP和CSP
- Select
- Docker
- 基本命令
- dockerfile
- docker-compose
- rpc和grpc
- consul和etcd
- ETCD
- consul
- gin
- 一些小點
- 樹
- K8s
- ES
- pprof
- mycat
- nginx
- 整理后的面試題
- 基礎
- Map
- Chan
- GC
- GMP
- 并發
- 內存
- 算法
- docker