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