亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在Go中,結構體指針不是引用類型嗎?

在Go中,結構體指針不是引用類型嗎?

Go
慕雪6442864 2023-08-07 14:47:59
我不明白 Go 變量的行為。我要你告訴我。請參閱下面的示例實現。package mainimport (    "fmt")func pointer(ip *Num) {    fmt.Printf("pointer type [%T] : %p\n", &ip, &ip)}func pointerpointer(ip **Num) {    fmt.Printf("pointerpointer type [%T] : %p\n", ip, ip)}func main() {    pnum := &Num{i: 3}    fmt.Printf("main type [%T] : %p\n", &pnum, &pnum)    pointer(pnum)    pointerpointer(&pnum)}type Num struct {    i int}https://play.golang.org/p/LxDAgopxeh0結果main type [**main.Num] : 0x40c138pointer type [**main.Num] : 0x40c148pointerpointer type [**main.Num] : 0x40c138我將 struct Num 指針存儲為變量 [pnum]。將其傳遞給指針函數時可以獲取的地址與在主函數中可以獲取的地址不同。為什么??已經證實,通過引用pointer指針作為pointer指針函數,可以獲得與main函數相同的地址。
查看完整描述

3 回答

?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

pnum中的main是一個實際變量:一個浮動在內存中的盒子,包含類型為 的指針*Num。


 0x40c138

+--------+

|    *---|--->

+--------+

指向什么pnum?好吧,Num{i: 3}創建了一個未命名的變量,漂浮在內存中的某個地方。我們還沒有打印出來。我修改了您的 Playground 示例,添加了一個fmt.Printf調用來找出答案:


main type [**main.Num] : 0x40c138

pnum points to [*main.Num] : 0x40e020

或者:


 0x40c138       0x40e020

+--------+     +--------+

|    *---|---> |  i: 3  |

+--------+     +--------+

現在讓我們繼續:main調用,將存儲在中的值pointer傳遞給它—該值讓計算機找到包含未命名實例的盒子。該值存儲在內存中的某個位置。那是在什么地方?為什么,這是您打印的數字,因為您打印了。幸運的是,Playground 具有很強的確定性,所以它也是我打印的:pnum0x40c138i=3&ip


pointer type [**main.Num] : 0x40c148

所以我們可以在繪圖中添加另一個框:


 0x40c138       0x40e020

+--------+     +--------+

|0x40e020|---> |  i: 3  |

+--------+     +--------+

                   ^

 0x40c148          |

+--------+         |

|0x40e020|---------+

+--------+

現在返回,丟棄保存 的pointer框,然后調用,作為值傳遞。函數現在在某個位置與一個框一起運行。那個位置在哪里?我們不知道;我們從不打印它。我們確實在該位置打印了盒子里的東西,盒子里的東西是:0x40c1480x40e020pointerpointer&pnumpointerpointer0x40c138


 0x40c138       0x40e020

+--------+     +--------+

|0x40e020|---> |  i: 3  |

+--------+     +--------+

    ^

    |

 ????????

+--------+

|0x40c138|

+--------+

我們可以在程序中再添加一個,fmt.Printf以查找最后一個框在內存中的實際位置,然后再次運行:


pointerpointer's &ip is [***main.Num] : 0x40c150

因此將八個問號替換為0x40c150。

這里的總體規則很簡單:每個變量都在某個地方存在,除非編譯器可以優化它。 使用 獲取變量的地址&x往往會阻止編譯器優化變量本身。的類型,其中&x空白pointer to ___是 的類型x。的值是變量&x的地址。

在這種情況下,你

  • 創建了一個匿名(未命名)Num實例,

  • 獲取它的地址(強制編譯器將其放入內存中的某個位置),并且

  • 將變量設置pnum為該值

(全部在第一行main)。然后你獲取了它本身的地址pnum,這意味著它pnum也必須存在于內存中的某個地方。這是我們最初畫的兩個盒子。您在第二行打印了該地址的類型和值。

然后,您將存儲在的值傳遞給pnum,func pointer后者將該值存儲在變量中。這樣就創建了另一個單獨的變量,它有自己的地址。

不用擔心函數pointer做了什么,然后您將地址傳遞pnumfunc pointerpointer。該地址是一個值,并將pointerpointer該值存儲在變量中。這也創建了另一個單獨的變量。

在這整個過程中,匿名者的地址從未動Numi=3。地址pnum本身也沒有。



查看完整回答
反對 回復 2023-08-07
?
慕標5832272

TA貢獻1966條經驗 獲得超4個贊

簡短的回答是:

指針通過值傳遞。

該函數pointer接收內存地址的副本。它將副本存儲在某個地方(可能是它自己的堆?;蚱渌麞|西)。

內存地址只是一個數字。

如果您定義一個數字main并獲取其地址,然后將該數字傳遞給另一個函數并獲取地址,您是否應該期望兩個地址相同?


查看完整回答
反對 回復 2023-08-07
?
慕婉清6462132

TA貢獻1804條經驗 獲得超2個贊

在Go中,結構體指針不是引用類型嗎?

不,只是因為Go沒有 引用 類型。

有幾種類型具有引用語義,切片是最突出的例子,但即使切片也是值類型而不是引用類型。

Go 中的指針是普通值和真正的機器級地址。當您傳遞內存地址時,不會發生“引用內容”。如果將內存地址存儲在變量中,則可以獲取該變量的地址。再次沒有類似的參考。在 Go 中它的值一直向下。

基本上就像C中的一樣。


查看完整回答
反對 回復 2023-08-07
  • 3 回答
  • 0 關注
  • 172 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號