3 回答

TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超1個(gè)贊
pnum中的main是一個(gè)實(shí)際變量:一個(gè)浮動(dòng)在內(nèi)存中的盒子,包含類型為 的指針*Num。
0x40c138
+--------+
| *---|--->
+--------+
指向什么pnum?好吧,Num{i: 3}創(chuàng)建了一個(gè)未命名的變量,漂浮在內(nèi)存中的某個(gè)地方。我們還沒有打印出來。我修改了您的 Playground 示例,添加了一個(gè)fmt.Printf調(diào)用來找出答案:
main type [**main.Num] : 0x40c138
pnum points to [*main.Num] : 0x40e020
或者:
0x40c138 0x40e020
+--------+ +--------+
| *---|---> | i: 3 |
+--------+ +--------+
現(xiàn)在讓我們繼續(xù):main調(diào)用,將存儲(chǔ)在中的值pointer傳遞給它—該值讓計(jì)算機(jī)找到包含未命名實(shí)例的盒子。該值存儲(chǔ)在內(nèi)存中的某個(gè)位置。那是在什么地方?為什么,這是您打印的數(shù)字,因?yàn)槟蛴×?。幸運(yùn)的是,Playground 具有很強(qiáng)的確定性,所以它也是我打印的:pnum0x40c138i=3&ip
pointer type [**main.Num] : 0x40c148
所以我們可以在繪圖中添加另一個(gè)框:
0x40c138 0x40e020
+--------+ +--------+
|0x40e020|---> | i: 3 |
+--------+ +--------+
^
0x40c148 |
+--------+ |
|0x40e020|---------+
+--------+
現(xiàn)在返回,丟棄保存 的pointer框,然后調(diào)用,作為值傳遞。函數(shù)現(xiàn)在在某個(gè)位置與一個(gè)框一起運(yùn)行。那個(gè)位置在哪里?我們不知道;我們從不打印它。我們確實(shí)在該位置打印了盒子里的東西,盒子里的東西是:0x40c1480x40e020pointerpointer&pnumpointerpointer0x40c138
0x40c138 0x40e020
+--------+ +--------+
|0x40e020|---> | i: 3 |
+--------+ +--------+
^
|
????????
+--------+
|0x40c138|
+--------+
我們可以在程序中再添加一個(gè),fmt.Printf以查找最后一個(gè)框在內(nèi)存中的實(shí)際位置,然后再次運(yùn)行:
pointerpointer's &ip is [***main.Num] : 0x40c150
因此將八個(gè)問號(hào)替換為0x40c150。
這里的總體規(guī)則很簡(jiǎn)單:每個(gè)變量都在某個(gè)地方存在,除非編譯器可以優(yōu)化它。 使用 獲取變量的地址&x
往往會(huì)阻止編譯器優(yōu)化變量本身。的類型,其中&x
空白pointer to ___
是 的類型x
。的值是變量&x
的地址。
在這種情況下,你
創(chuàng)建了一個(gè)匿名(未命名)
Num
實(shí)例,獲取它的地址(強(qiáng)制編譯器將其放入內(nèi)存中的某個(gè)位置),并且
將變量設(shè)置
pnum
為該值
(全部在第一行main
)。然后你獲取了它本身的地址pnum
,這意味著它pnum
也必須存在于內(nèi)存中的某個(gè)地方。這是我們最初畫的兩個(gè)盒子。您在第二行打印了該地址的類型和值。
然后,您將存儲(chǔ)在的值傳遞給pnum
,func pointer
后者將該值存儲(chǔ)在變量中。這樣就創(chuàng)建了另一個(gè)單獨(dú)的變量,它有自己的地址。
不用擔(dān)心函數(shù)pointer
做了什么,然后您將地址傳遞pnum
給func pointerpointer
。該地址是一個(gè)值,并將pointerpointer
該值存儲(chǔ)在變量中。這也創(chuàng)建了另一個(gè)單獨(dú)的變量。
在這整個(gè)過程中,匿名者的地址從未動(dòng)Num
過i=3
。地址pnum
本身也沒有。

TA貢獻(xiàn)1966條經(jīng)驗(yàn) 獲得超4個(gè)贊
簡(jiǎn)短的回答是:
指針通過值傳遞。
該函數(shù)pointer
接收內(nèi)存地址的副本。它將副本存儲(chǔ)在某個(gè)地方(可能是它自己的堆?;蚱渌麞|西)。
內(nèi)存地址只是一個(gè)數(shù)字。
如果您定義一個(gè)數(shù)字main
并獲取其地址,然后將該數(shù)字傳遞給另一個(gè)函數(shù)并獲取其地址,您是否應(yīng)該期望兩個(gè)地址相同?

TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超2個(gè)贊
在Go中,結(jié)構(gòu)體指針不是引用類型嗎?
不,只是因?yàn)?strong>Go中沒有 引用 類型。
有幾種類型具有引用語義,切片是最突出的例子,但即使切片也是值類型而不是引用類型。
Go 中的指針是普通值和真正的機(jī)器級(jí)地址。當(dāng)您傳遞內(nèi)存地址時(shí),不會(huì)發(fā)生“引用內(nèi)容”。如果將內(nèi)存地址存儲(chǔ)在變量中,則可以獲取該變量的地址。再次沒有類似的參考。在 Go 中它的值一直向下。
基本上就像C中的一樣。
- 3 回答
- 0 關(guān)注
- 182 瀏覽
添加回答
舉報(bào)