Go 傳 slice 是複製 header 而不是 pass by reference
Go 只有 pass by value,沒有 pass by reference。 傳 slice 進 function 時被複製的是那個三欄位的 slice header:複製了窗戶的框,玻璃後面的房子還是同一間。
func f(w []string) { w[0] = "Hi" } // 外面看得到
func g(w []string) { w = append(w, "x") } // 外面看不到| 在 function 裡做的事 | 外面看得到嗎 | 為什麼 |
|---|---|---|
w[0] = "Hi" | ✅ | 順著副本的 ptr,改到同一塊 array |
w = []string{"XXX"} | ❌ | 只換掉了副本的 ptr |
w = append(w, "x") | ❌ | 改的是副本的 len(或副本的 ptr) |
第三列最容易誤解:cap 夠時,那個 "x" 確實被寫進了共用的 array,但呼叫端 header 的 len 沒變,所以它看不到那個元素。cap 不夠時更徹底——副本直接指向另一塊 array,兩邊從此無關。
如果真的是 pass by reference,第二、三列也會反映到外面。這正是為什麼 append 一定要寫成 s = append(s, x):呼叫端必須自己接回新的 header。
跟 JS 傳物件的直覺一致:f(o){ o.a = 1 } 改得到,f(o){ o = {} } 改不到。