一切都是傳值
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