了解結構體類型的 Setter
在 Go 中,可以透過 setter 函數修改結構體。但是,在對結構類型使用 setter 時,某些行為可能是無法預料的。考慮以下範例:
package main import "fmt" type T struct { Val string } // this setter seems not to work func (t T) SetVal(s string) { t.Val = s } // this setter, using ptr to T, seems to work ok func (t *T) SetVal2(s string) { (*t).Val = s } func main() { v := T{"abc"} fmt.Println(v) // prints {abc} v.SetVal("pdq") fmt.Println(v) // prints {abc}, was expecting {pdq}! v.SetVal2("xyz") fmt.Println(v) // prints {xyz}! }
問題出現了:為什麼 SetVal 函數沒有如預期修改原始結構?
理解值語意
主要區別在於結構體如何傳遞給函數。當以值傳遞結構體時(如 SetVal),會在函數內建立該結構體的副本。函數內所做的任何變更只會影響此暫存副本,而原始結構保持不變。
但是,當透過指標傳遞結構時(如 SetVal2 中),函數可以存取記憶體中的原始結構。函數內所做的任何更改都將直接反映在原始結構中。
價值語意證明
這可以透過列印所涉及結構的記憶體位址來說明:
package main import "fmt" type T struct { Val string } func (t T) SetVal(s string) { fmt.Printf("Address of copy is %p\n", &t) } func (t *T) SetVal2(s string) { fmt.Printf("Pointer argument is %p\n", t) } func main() { v := T{"abc"} fmt.Printf("Address of v is %p\n", &v) v.SetVal("pdq") v.SetVal2("xyz") }
此程式碼將產生輸出類似於:
Address of v is 0xf840001290 Address of copy is 0xf8400013e0 Pointer argument is 0xf840001290
注意,列印的第一個和第三個位址是相同的,表示它們引用相同的結構體。然而,第二個位址不同,代表在 SetVal 中建立的暫存副本。
以上是為什麼我的 Go Struct Setter 函數沒有修改原始結構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!