Learn Go Pointer and Difference with Passing by Reference

学习 Go Pointer 与 Passing by reference 的差异

一切都是传值

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
}

但在处理一些数值像是:SlicesMapsFunctions 时会遇到像是「Passing by reference」的行为,实际上是因为虽然是传递数值,只是数值是「Pointer」指向另一个记忆体位置。

通过 & 获取变量的记忆体位址、通过 * 获取记忆体位址的数值:

name := "foo"
namePointer := &name
fmt.Println(&name) // 0x14000122020
fmt.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 (内含指针的值类型)
StringsSlices
IntsMaps
FloatsFunctions
Booleans
Arrays
Structs
  • Go 一切都是 Passing by Value
  • Reference Types 带有指针,复制时是复制指针
  • 要让 Value Types 有 Passing by Reference 的效果要显式的使用 Pointer

Passing by Reference 是其他语言如 C++ 或 C# 的特性,相当于编译器直接将「变量本身」绑定到函数参数,不用再通过操作 Pointer 等动作。

延伸阅读