指针
指针保存某个变量的内存地址。通过指针可以间接读取或修改该变量的值,并避免大对象在函数间传递时的完整拷贝。
取地址与解引用
& 获取变量地址(取地址),* 通过地址访问目标值(解引用):
指针类型写作 *T(如 *int、*User),表示"指向 T 的指针"。
为什么需要指针:值传递语义
Go 的函数参数与赋值均为值拷贝。函数内部修改参数副本不会影响原值;需要跨函数修改或避免拷贝时,必须传递指针:
:::tip 选择值还是指针的实践经验:
- 需要修改原值、或结构体较大需要避免拷贝时,传指针。
- 小型只读数据(如
time.Time)传值更安全,可避免调用方数据被意外修改。 - 切片、映射本身是引用语义的结构,通常无需再取指针。 :::
nil 指针与安全性
未指向任何变量的指针为零值 nil。对 nil 指针解引用会触发 panic(运行时崩溃):
nil 指针也有惯用价值:结构体方法的指针接收者可以为 nil 并在方法内部处理,例如标准库中 (*bytes.Buffer)(nil) 场景的空判断。
new 与指针的创建
除 & 外,new(T) 分配一块零值的 T 内存并返回其指针:
new 适用于"先要一个零值指针"的场景;有初始值时通常直接写 &User{Name: "Alice"}。
没有指针运算
与 C 不同,Go 不支持对指针做加减运算(p++、p+1 均为编译错误),也不支持指针与整数互转。这一设计牺牲了少量灵活性,换取了内存安全与垃圾回收的高效实现。
与后续章节的关联
小结
&取地址,*解引用;指针类型为*T。- Go 一切传参皆拷贝;跨函数修改或避免大对象拷贝时使用指针。
- nil 指针解引用会 panic,解引用前必须判空;Go 无指针运算。