贝利信息

如何区分Golang指针传递与引用传递_Golang语言特性澄清

日期:2026-01-19 00:00 / 作者:P粉602998670
Go语言所有函数参数都是值传递,包括指针:传的是地址值的副本,而非引用;slice/map/channel是含指针的值类型,故能修改底层数组但扩容不影响原变量。

Go 语言根本没有引用传递

直接说结论:Go 所有函数参数都是值传递,func f(x *int) 传的不是“引用”,而是“地址的副本”。所谓“引用传递”是 C++/Java 等语言的概念,Go 从语法到运行时都不支持。初学者常把 *T 参数行为误称为“引用传递”

,其实是混淆了“效果”和“机制”——你确实能修改原值,但底层仍是复制了一个 8 字节的地址值。

指针传递 vs 值传递:看改不改得到原变量

关键区别不在“怎么传”,而在“传的是什么值”:

func reassign(p *int) {
    b := 20
    p = &b // 只改了副本 p,不影响外面的指针
}
func main() {
    a := 10
    p := &a
    reassign(p)
    fmt.Println(*p) // 还是 10,不是 20
}

为什么 slice/map/channel 看起来像“引用传递”?

它们不是引用类型,而是**含指针的值类型**。例如 []int 底层是 struct{ ptr *int, len, cap },传参时复制这个 struct,但 ptr 字段指向同一片底层数组。所以 s[0] = 100 能生效,不是因为“引用”,而是因为复制后的 struct 仍持有原数据地址。

什么时候该用指针?三个硬判断条件

别凭感觉,按这三条来:

最易被忽略的一点:nil 指针解引用会 panic,而值类型不会;所以用指针前,要么确保非 nil,要么显式判空——这不是风格问题,是运行时安全边界。