(譯)Go 語(yǔ)言的內(nèi)存、指針詳解

原文鏈接:Understand Go pointers in less than 800 words or your money back

這是一篇面向即將學(xué)習(xí) go 語(yǔ)言并且對(duì)指針理念或者 go 的指針類型不是很了解的程序員的內(nèi)容

什么是指針?

簡(jiǎn)單解釋,指針就是指向另一段地址的值,課本上是這么解釋的,但是如果你是一個(gè)來(lái)自并不討論變量地址開發(fā)語(yǔ)言的開發(fā)者,使用指針進(jìn)行編程將感覺非常的美妙。

我們先換一個(gè)話題

什么是內(nèi)存?

計(jì)算機(jī)的內(nèi)存 RAM 可以把它想象成一些有序的盒子,一個(gè)接一個(gè)的排成一排,每一個(gè)盒子或者單元格都被一個(gè)唯一的數(shù)字標(biāo)記依次遞增,這個(gè)數(shù)字就是該單元格的地址,也就是內(nèi)存的地址。


image.png

每一個(gè)單元格存儲(chǔ)單一的值,如果你知道一個(gè)單元格的地址,那么你就可以通過(guò)地址讀取單元格中的內(nèi)容。你也可以向這個(gè)單元格中放置一個(gè)值來(lái)替代之前的任何值。

這就是關(guān)于內(nèi)存的所有內(nèi)容。CPU 所做的一切操作也都是在讀取或者存儲(chǔ)單元格中值。

什么是變量?

編寫一段程序,檢索出值并存儲(chǔ)在地址為 200 的一個(gè)塊內(nèi)存中,將其乘以 3,并將結(jié)果存儲(chǔ)在地址為 201 的另一塊內(nèi)存中,我們就可以像這樣寫一段偽代碼:

  1. 檢索出內(nèi)存地址為 200 的值,并將其存儲(chǔ)在 CPU 中
  2. 將存儲(chǔ)在 CPU 中的值乘以 3
  3. 將 CPU 中存儲(chǔ)的結(jié)果,寫入地址為 201 的內(nèi)存塊中


    image.png

這是相當(dāng)早期的編程形式,程序員需要維護(hù)一列內(nèi)存地址,需要清楚的知道:誰(shuí)、什么時(shí)候在使用它以及內(nèi)存中存儲(chǔ)的值是什么。

很顯然這是非常枯燥又很容易出錯(cuò)的方式,并且還意味著你要為程序構(gòu)建過(guò)程中內(nèi)存中的每一個(gè)可能出現(xiàn)的值分配地址。更糟糕的是這種設(shè)計(jì)使得你動(dòng)態(tài)的為變量分配存儲(chǔ)變得很艱難,你可以想象一下如果編寫一個(gè)大型的程序而只能使用全局變量是什么感受?

為了解決這個(gè)問題,變量的概念被創(chuàng)造了出來(lái),一個(gè)變量?jī)H僅是一個(gè)代表內(nèi)存地址的字母數(shù)字組合、也可以一個(gè)標(biāo)簽或者一個(gè)昵稱 。

現(xiàn)在,我們與其探討內(nèi)存地址,不如說(shuō)一下變量,變量是我們?yōu)閮?nèi)存地址賦予的一個(gè)更容易理解的名稱,之前的那個(gè)程序現(xiàn)在可以這樣的解釋一下:

image.png
  1. 獲取變量 a 中存儲(chǔ)的值,并將其存儲(chǔ)在 CPU 中
  2. 將其乘以 3
  3. 將結(jié)果保存在變量 b 中

這是一個(gè)相同的程序,唯一的一個(gè)重要改進(jìn)是我們不在直接關(guān)注內(nèi)存地址了,我們也不在需要持續(xù)追蹤內(nèi)存地址,而是把這個(gè)苦差事交給了編譯器。

現(xiàn)在我們可以像這樣寫程序了:

var a = 6 
var b = a * 3

編譯器將確保 a 與 b 的變量被分配唯一的地址,同時(shí)保證其值可以在被調(diào)用結(jié)束之前不被釋放。

到底什么是指針呢?

截止目前我們知道了內(nèi)存就是一系列有序列號(hào)的存儲(chǔ)單元,變量就是編譯器為內(nèi)存地址分配的昵稱,那么指針是什么呢?

指針就是一個(gè)指向另一個(gè)內(nèi)存地址變量的值

指針指向變量的內(nèi)存地址,指針就像該變量值的內(nèi)存地址一樣

我們來(lái)看一個(gè)代碼片段

func main() {
    a := 200
    b := &a
    *b++
    fmt.Println(a)
}

在 main 函數(shù)的第一行,我們定義了一個(gè)新的變量 a ,并賦值為 200。接下來(lái)我們定義了一個(gè)變量 b ,并將變量 a 的地址賦值給 b 。我們并不知道 a 的準(zhǔn)確存儲(chǔ)地址,但是我們依然可以將 a 的地址存儲(chǔ)在變量 b 中。

image.png
image.png

因?yàn)?Go 強(qiáng)類型的特性,第三行代碼也許是最具干擾性的了,b 包含 a 變量的地址,但是我們想增加存儲(chǔ)在 a 變量中的值。這樣我們必須取消引用 b ,而是跟隨指針由 b 引用 a。
然后我們將該值加 1 后,存儲(chǔ)回 b 中存儲(chǔ)的內(nèi)存地址上。
最后一行打印了 a 的值,可以看到 a 的值已經(jīng)增加為了 201

image.png
image.png

結(jié)論

假如你是一個(gè)來(lái)自沒有指針概念或者變量中隱藏了指針的開發(fā)語(yǔ)言的開發(fā)者,你需要在形成一個(gè)指針與變量關(guān)聯(lián)關(guān)系的模型,總之記住這個(gè)規(guī)則:

指針是一個(gè)指向另一個(gè)變量?jī)?nèi)存地址的值

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 指針是C語(yǔ)言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語(yǔ)言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,606評(píng)論 3 44
  • void* 類型指針:通用變體類型指針;可以不經(jīng)轉(zhuǎn)換,賦給其他指針,函數(shù)指針除外;malloc返回的就是void*...
    冰吉凌閱讀 3,511評(píng)論 0 18
  • 1.語(yǔ)言中變量的實(shí)質(zhì) 要理解C指針,我認(rèn)為一定要理解C中“變量”的存儲(chǔ)實(shí)質(zhì), 所以我就從“變量”這個(gè)東西開始講起吧...
    金巴多閱讀 1,972評(píng)論 0 9
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場(chǎng)景。SDWebImage的原...
    LZM輪回閱讀 2,108評(píng)論 0 12
  • 看完心理學(xué)的書,再看小說(shuō),覺得好表面……
    深海綠妖閱讀 499評(píng)論 0 1

友情鏈接更多精彩內(nèi)容