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