Learn Go Pointer and Difference with Passing by Reference

學習 Go Pointer 與 Passing by reference 的差異

一切都是傳值

Go 設計上一切數值都是直白的「Passing by value」,可參考以下範例:

func updateName(newName string){
newName = "bar"
}
func main() {
name := "foo"
updateName(name)
fmt.Println(name) // foo
}

Go 會將變數的值複製一份到新的區域變數 newName。對 newName 的修改不會影響外部的 name,因為兩者已經是不同的變數。

Pointer 包裝的數值

func updateName(data map[string]string) {
data["name"] = "bar"
}
func main() {
data := map[string]string{
"name": "foo",
}
updateName(data)
fmt.Println(data["name"]) // bar
}

但在處理一些數值像是:SlicesMapsFunctions 時會遇到像是「Passing by reference」的行為,實際上是因為雖然是傳遞數值,只是數值是「Pointer」指向另一個記憶體位置。

透過 & 取得變數的記憶體位址、通過 * 取得記憶體位址的數值:

name := "foo"
namePointer := &name
fmt.Println(&name) // 0x14000122020
fmt.Println(*namePointer) // foo

回到剛剛的案例,透過傳遞 Pointer 而非數值就能達成在「Passing by value」的模式下建立 name 並修改 name 的目的:

func updateName(newName *string){
*newName = "bar"
}
func main() {
name := "foo"
updateName(&name)
fmt.Println(name) // bar
}

總結

Value Types (純值類型)Reference Types (內含指標的值類型)
StringsSlices
IntsMaps
FloatsFunctions
Booleans
Arrays
Structs
  • Go 一切都是 Passing by Value
  • Reference Types 帶有指標,複製時是複製指標
  • 要讓 Value Types 有 Passing by Reference 的效果要顯式的使用 Pointer

Passing by Reference 是其他語言如 C++ 或 C# 的特性,相當於編譯器直接將「變數本身」綁定到函式參數,不用再透過操作 Pointer 等動作。

延伸閱讀