在 Go 语言中,指针传递传递的是指针的副本,而这个指针本身是一个内存地址的值。所以更精确地说,传递的是内存地址的副本。
让我详细解释一下:
-
指针是什么?
- 在 Go 中,指针是一个变量,它存储的是另一个变量的内存地址。比如
var p *int
,p
是一个指针,指向某个整数的内存地址。 - 内存地址本身是一个值(通常是 64 位或 32 位整数,取决于系统架构)。
- 在 Go 中,指针是一个变量,它存储的是另一个变量的内存地址。比如
-
指针传递的过程
- 当你将一个指针传递给函数时,比如
func foo(p *int)
,Go 会将这个指针的值(即内存地址)复制一份,传递给函数。 - 函数接收到的
p
是原始指针的副本,但这个副本仍然指向相同的内存地址。 - 因为是指向同一地址,函数可以通过解引用(
*p
)修改原始值。
- 当你将一个指针传递给函数时,比如
-
为什么说是“内存地址的副本”?
- 传递的不是原始指针变量本身,而是它的值(内存地址)的副本。
- 这意味着函数内部如果修改了指针变量本身(比如让
p
指向另一个地址),不会影响调用处的原始指针。但如果修改的是指针指向的内容(*p
),则会影响原始值。
示例代码
package mainimport "fmt"func modifyPointer(p *int) {fmt.Printf("函数内指针地址: %p\n", p) // p 是指针的副本*p = 100 // 修改指针指向的内容
}func reassignPointer(p *int) {x := 200p = &x // 修改 p 本身,让它指向新地址
}func main() {a := 10fmt.Printf("原始指针地址: %p\n", &a)modifyPointer(&a)fmt.Println("修改后 a 的值:", a) // 输出 100reassignPointer(&a)fmt.Println("尝试重新赋值后 a 的值:", a) // 输出 100,未改变
}
输出解释
modifyPointer(&a)
:函数内的p
是&a
的副本,指向同一个地址,修改*p
会改变a
的值。reassignPointer(&a)
:函数内的p
是副本,重新赋值p = &x
只影响副本,不影响原始的&a
,所以a
不变。
结论
- 指针传递传递的是指针的副本,这个副本是一个内存地址的值。
- 函数内部可以通过这个地址修改原始数据,但如果修改指针本身(让它指向新地址),不会影响外部的原始指针。
希望这个解释清楚了你的疑问!如果还有困惑,欢迎继续提问!