Go 语言中不存在引用传递:深层次剖析值传递的本质
2023-10-21 04:04:58
Go 语言中不存在引用传递
Go 语言中从来就不存在所谓的“引用传递”,从来就只有一种变量传递方式,那就是值传递。因为引用传递的前提是存在“引用变量”,但是 Go 语言中从来就没有出现过所谓的“引用变量”。
理解值传递
值传递是指将变量的值从一个变量复制到另一个变量。在这个过程中,两个变量是独立的,互不影响。例如:
package main
func main() {
var a = 10
var b = a
a++
fmt.Println(a, b) // 输出:11 10
}
在这个例子中,我们定义了两个变量 a
和 b
,并通过赋值操作将 a
的值复制到了 b
。当我们对 a
的值进行修改时,b
的值不会受到影响。这说明 a
和 b
是两个独立的变量,a
的值的变化不会影响 b
的值。
引用类型的本质
在 Go 语言中,引用类型是指指向其他变量或数据的变量。引用类型本身不存储实际的值,而是存储指向实际值的内存地址。例如:
package main
type Person struct {
name string
age int
}
func main() {
var p1 = Person{name: "John", age: 30}
var p2 = p1
p1.name = "Mary"
fmt.Println(p1.name, p2.name) // 输出:Mary Mary
}
在这个例子中,我们定义了一个结构体 Person
,并通过赋值操作将 p1
的值复制到了 p2
。当我们对 p1
的 name
属性进行修改时,p2
的 name
属性的值也会受到影响。这说明 p1
和 p2
指向同一个 Person
结构体,p1
对 Person
结构体的修改也会影响到 p2
。
但是,需要注意的是,p1
和 p2
仍然是两个独立的变量,p1
的值的变化不会影响 p2
的内存地址。例如:
package main
type Person struct {
name string
age int
}
func main() {
var p1 = Person{name: "John", age: 30}
var p2 = p1
fmt.Println(&p1, &p2) // 输出:0xc00009e0c8 0xc00009e0d0
}
在这个例子中,我们打印了 p1
和 p2
的内存地址,可以看到两个变量的内存地址是不同的。这说明 p1
和 p2
仍然是两个独立的变量,p1
的值的变化不会影响 p2
的内存地址。
理解指针传递
在 Go 语言中,指针变量是指向其他变量或数据的内存地址的变量。指针变量本身不存储实际的值,而是存储指向实际值的内存地址。例如:
package main
func main() {
var a = 10
var p = &a
*p++
fmt.Println(a, *p) // 输出:11 11
}
在这个例子中,我们定义了一个变量 a
和一个指针变量 p
,并通过取地址运算符 &
将 a
的内存地址赋值给了 p
。当我们对 *p
的值进行修改时,a
的值也会受到影响。这说明 p
指向 a
的内存地址,*p
的值的变化会影响到 a
的值。
但是,需要注意的是,p
和 a
仍然是两个独立的变量,p
的值的变化不会影响 a
的内存地址。例如:
package main
func main() {
var a = 10
var p = &a
fmt.Println(&a, p) // 输出:0xc00009e0c8 0xc00009e0d0
}
在这个例子中,我们打印了 a
的内存地址和 p
的值,可以看到两个变量的内存地址是不同的。这说明 p
和 a
仍然是两个独立的变量,p
的值的变化不会影响 a
的内存地址。
总结
综上所述,Go 语言中不存在引用传递,只有值传递和指针传递。值传递是指将变量的值从一个变量复制到另一个变量,而指针传递是指将变量的内存地址从一个变量复制到另一个变量。值传递和指针传递都是独立的变量传递方式,互不影响。