Go语言无引用类型,仅支持指针;必须传*T修改值类型变量、避免大结构体拷贝、实现可修改方法接收者;需警惕nil解引用、切片元素地址失效及返回局部变量地址等陷阱。

Go 里没有引用类型,只有指针
Go 语言从设计上就**不支持 C++ 那种语法层面的引用(&)**,也没有引用语义的变量声明。所谓“模拟”,本质是用 *T 指针显式传递地址,并在函数内通过 *p 解引用修改原值。这不是语法糖,而是明确的内存操作——你得自己管好生命周期、空指针和所有权边界。
什么时候必须传 *T 而不是 T
当函数需要修改调用方的变量值,且该变量是值类型(int、struct、[3]int 等)时,必须传指针。传值只会拷贝一份,改了也没用。
-
func increment(x int) { x++ }→ 调用后原变量不变 -
func increment(x *int) { *x++ }→ 必须传&v,才能改v - 结构体较大时,传
*S避免拷贝开销(哪怕你不修改它) - 方法接收者用指针(
func (s *S) SetName(n string))才能修改字段
常见错误:nil 指针解引用和意外共享
Go 不做空指针防护,*p 前不检查 p == nil 就 panic;另外,多个地方持有同一指针,可能引发竞态或意料外的修改。
- 传
nil给*string参数却直接*s = "x"→panic: runtime error: invalid memory address or nil pointer dereference - 对切片元素取地址:
&slice[i]在 slice 扩容后可能失效(底层数组被替换) - 把局部变量地址返回:
func bad() *int { x := 42; return &x }→ 返回后x已出栈,行为未定义(Go 编译器通常会逃逸分析并分配到堆,但逻辑上仍危险)
和 C++ 引用的关键差异点
C++ 的 int& r = x 是别名,不可重绑定、不能为空;Go 的 *int 是可变地址、可为 nil、可重新赋值指向别处——语义更接近 C 的指针,而非 C++ 引用。
立即学习“go语言免费学习笔记(深入)”;
- C++ 引用参数隐式传递,Go 指针参数必须显式写
&v - C++ 可以
const int& r = x实现只读引用;Go 没有 const,靠约定或封装(如只暴露 getter 方法) - 结构体字段不能是指针类型“引用”另一个字段(Go 不支持字段引用),只能存值或指针
- 接口值本身是
(type, value)二元组,传接口时若底层是大对象,仍可能触发拷贝 —— 这点容易被忽略










