我不明白這段程式碼到底發生了什麼事。
接收方 func 在原始結構 user 上工作(因為指標),因此在 func 內部我們更改了原始 obj。但是結構地址也是原始的還是原始“a”的副本?
func main() { a := address{"freedom", "kyiv"} u := user{"valeriy", "zalyzhnyi", a} fmt.println(a) fmt.println(u) u.updatestreet("peremohy") fmt.println(a) fmt.println(u) } func (u *user) updatestreet(street string) { u.address.street = street } type user struct { firstname string lastname string address address } type address struct { street string city string }
這是我的輸出
{Freedom Kyiv} {Valeriy Zalyzhnyi {Freedom Kyiv}} {Freedom Kyiv} {Valeriy Zalyzhnyi {Peremohy Kyiv}}
由此我了解到 u.address 已更改,而且我還看到“u”內的“a”與原始的 obj 不同。 那麼幕後和記憶體中究竟發生了什麼事? 根據輸出,這種行為對我來說是完全出乎意料的。 我期望由於指標的存在,我們在兩種情況下都使用原始物件(“a”和“u”)。第二次(在func 'update..' 之後)列印fmt.println(a) 將為我們提供{peremohy kyiv},因為第二次fmt.println(u) 為我們提供{valeriy zalyzhnyi {peremohy kyiv}}
要了解幕後發生的情況,視覺化程式碼的作用可能會很有用:
a = address{} u := user{address: a}
細分為:
| variable value | memory address | | a = address{} | 0x000001 | | u = user{} | 0x000002 | | u.address = copy of a | 0x000003 |
因此,您已為 1 個 user{}
實例和 2 個 address{}
實例分配了記憶體。第二個位址實例的值是第一個位址實例的精確副本(在建立副本時)。
現在,當您呼叫updatestreet
時,它是透過指標在u
上呼叫的,它不會建立user
實例的副本,而是對記憶體位址0x000002
進行操作,因此它實際上會對同一個a
變數進行操作。因此表達式:
u.address.street = "foo"
翻譯為:在記憶體位址 0x000002 中儲存的值上,存取名為 address
的字段,在該字段中,存取字段 street
並為其分配新值。讓我們將其映射到我們上面創建的表上:
0x000002 -> address (which is stored in 0x000003) | --> set street to "foo"
函數返回後,我們在記憶體中的相同位置仍然擁有與之前相同的對象,但是因為我們透過記憶體中的位址存取了a
的值,所以updatestreet
函數所做的更改已經完成為u
的值(因為我們使用了相同的記憶體位址)。
變數a
在賦值給u.address
時被複製,因此它的記憶體位址未知,或傳遞給updatestreet
函數,因此保持不變。
以上是這些結構的幕後發生了什麼事? struct 會被複製嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!