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