原文鏈接: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)存的地址。

每一個(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)存中,我們就可以像這樣寫一段偽代碼:
- 檢索出內(nèi)存地址為 200 的值,并將其存儲(chǔ)在 CPU 中
- 將存儲(chǔ)在 CPU 中的值乘以 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)在可以這樣的解釋一下:

- 獲取變量 a 中存儲(chǔ)的值,并將其存儲(chǔ)在 CPU 中
- 將其乘以 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 中。


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


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