一切都是傳值
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}
但在處理一些數值像是:Slices
、Maps
、Functions
時會遇到像是「Passing by reference」的行為,實際上是因為雖然是傳遞數值,只是數值是「Pointer」指向另一個記憶體位置。
透過 &
取得變數的記憶體位址、通過 *
取得記憶體位址的數值:
name := "foo"namePointer := &name
fmt.Println(&name) // 0x14000122020fmt.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 (內含指標的值類型) |
---|---|
Strings | Slices |
Ints | Maps |
Floats | Functions |
Booleans | |
Arrays | |
Structs |
- Go 一切都是 Passing by Value
- Reference Types 帶有指標,複製時是複製指標
- 要讓 Value Types 有 Passing by Reference 的效果要顯式的使用 Pointer
Passing by Reference 是其他語言如 C++ 或 C# 的特性,相當於編譯器直接將「變數本身」綁定到函式參數,不用再透過操作 Pointer 等動作。
延伸閱讀
- Go (Golang) Tutorial #13 - Pass By Value - Net Ninja
- Go (Golang) Tutorial #14 - Pointers - Net Ninja
- JavaScript 傳值與傳址,都幾咧? - WebDong