本篇是根據(jù) GopherCon SG 2019 “Understanding Allocations” 演講的學(xué)習(xí)筆記。
站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到扶風(fēng)網(wǎng)站設(shè)計(jì)與扶風(fēng)網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類(lèi)型包括:網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、國(guó)際域名空間、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋扶風(fēng)地區(qū)。
Understanding Allocations: the Stack and the Heap - GopherCon SG 2019 - YouTube
你的程序中有兩種內(nèi)存,棧內(nèi)存和堆內(nèi)存。
go 中,每個(gè) go 程都會(huì)有一個(gè)??臻g,整個(gè)程序有一個(gè)堆空間。
負(fù)責(zé)堆垃圾回收的 GC 會(huì)導(dǎo)致整個(gè)程序的延遲,而不僅僅是創(chuàng)建垃圾的部分。你可能會(huì)擔(dān)心你的代碼在堆中產(chǎn)生了多少垃圾。
要有 benchmarks 基準(zhǔn)來(lái)證明你的程序不夠快(有大量的堆內(nèi)存分配),夠快就不用多此一舉了。
你要先確保程序能正確運(yùn)作(業(yè)務(wù)處理),而不是先著重性能優(yōu)化。
在有大量指針+運(yùn)行快速的程序、清晰明了+但有點(diǎn)慢的程序之間,你應(yīng)該選擇后者。
函數(shù)和局部變量被擠壓入棧,一個(gè)函數(shù)為一個(gè)堆棧幀。
執(zhí)行完成后,你會(huì)發(fā)現(xiàn)黑線(只是用于區(qū)分)向上移,上方內(nèi)容為有效內(nèi)容,下方內(nèi)容為無(wú)效內(nèi)容(過(guò)期而不再使用)
go 聲明了新的內(nèi)存部分,我們有了新的堆棧幀用于打印行,黑線下移。
通俗的來(lái)講,??臻g會(huì)進(jìn)行自我清理,任何變量都會(huì)被清理干凈,空間會(huì)被重復(fù)使用。
main 函數(shù)和變量 n 被壓入棧。
inc 函數(shù)和變量 x 被壓入棧,屬于另一個(gè)堆棧幀,黑線下移。傳入的變量是 n 的地址。
黑線上移,n 被修改了值。并沒(méi)有什么問(wèn)題。
雖然使用了指針傳參,但這種情況下它能夠留在棧上,即共享向下傳遞時(shí),通常留在棧空間上。(主函數(shù)將自己的變量傳給子函數(shù))
編譯器推斷出 n 是 int 的指針類(lèi)型,賦初值 nil 等待函數(shù)返回結(jié)果。
在函數(shù)內(nèi)部聲明了變量并初始化,并返回了變量的內(nèi)存地址。
你會(huì)發(fā)現(xiàn),我明明沒(méi)有進(jìn)行賦值修改的操作,但卻破壞了原有的值。原因在于
answer
函數(shù)的時(shí)候,假如我們把聲明的變量 x
放在棧空間,返回變量的地址。main
函數(shù)中的 n
會(huì)拿到 x
的地址,當(dāng) answer
方法退出時(shí)(黑線上移),該堆棧幀已過(guò)期,但是 n
還引用著 x
。println
,黑線下移,產(chǎn)生新的堆棧幀,原先 x
標(biāo)識(shí)符被替換成了 a
,修改 a
的值等同修改了 n
地址解引用后的值。這是非常致命的錯(cuò)誤。為了解決上述致命的問(wèn)題,被聲明初始化的 x
變量就需要“逃逸”到堆空間中。這樣其他無(wú)關(guān)函數(shù)就不會(huì)對(duì)它的值產(chǎn)生影響。
共享向上傳遞時(shí),通常留在堆空間上。(子函數(shù)將自己的變量傳給主函數(shù),引用)
變量只在函數(shù)里工作,那就分配到棧空間上。如果編譯器不能證明函數(shù)返回后聲明過(guò)的變量是否被引用,那必須將其分配到堆空間上。
查看構(gòu)建指令,可以提供一個(gè) -gcflags 的可選參數(shù),傳遞給 go tool compile 工具
查詢 go tool compile -h,得知參數(shù) -m 可以輸出編譯器的優(yōu)化決定(變量放在棧還是堆上)
執(zhí)行 go build -gcflags "-m" 獲取到下面的結(jié)果
什么時(shí)候會(huì)把變量分配在堆內(nèi)存上
看看前面總結(jié)的第一點(diǎn)和第三點(diǎn)。明顯可以知道右邊那個(gè)是分配在棧上,而左邊那個(gè)分配在堆上。
io
標(biāo)準(zhǔn)庫(kù)里有個(gè) Reader
接口,你應(yīng)該知道為什么官方要用前者替換后者了吧。如果使用后者,會(huì)在堆上產(chǎn)生大量的垃圾,造成程序遲鈍。前者則符合向下傳遞思想,變量通常分配在棧空間上。
不要猜想,多用工具!
網(wǎng)站名稱(chēng):GopherCon SG 2019 "Understanding Allocations" 學(xué)習(xí)筆記
網(wǎng)站地址:http://chinadenli.net/article36/dsoissg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、App開(kāi)發(fā)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)