传指针能改原变量是因为Go中所有参数都是值传递,&x传入的是地址副本,但该副本与原指针指向同一内存,故*p = 100修改的是原变量x。

为什么传指针能改原变量?
Go 所有参数都是值传递,&x 传进去的其实是个地址副本,但它和原指针指向同一块内存。所以函数里写 *p = 100,改的是 x 本体,不是副本。
常见错误现象:传普通变量进函数,改了没用;传 *int 却忘了加 &,编译报错 cannot use … (type int) as type *int in argument to …。
- 结构体、大数组、切片底层数组——优先传
*Struct避免复制开销 - 小类型(
int、bool、string)——直接传值更清晰,没必要套一层指针 - 函数签名要求
*T时,调用处必须显式写&v,不能省略
nil 指针解引用 panic 怎么防?
nil 是所有指针类型的零值,*p 前不检查就等于埋雷。panic 错误信息通常是:panic: runtime error: invalid memory address or nil pointer dereference。
这不是编译期错误,运行到那行才炸,尤其容易出现在 map 查 key 后取字段、接口断言后解引用、或可选参数未初始化的场景。
立即学习“go语言免费学习笔记(深入)”;
- 任何接收
*T参数的函数,第一行建议先判if p == nil - 从 map 或 channel 接收指针类型值时,要当心它可能是
nil,别直接*p - 用
new(T)初始化比var p *T更安全,至少保证非nil(但注意new返回的是零值指针,不是空结构体)
结构体方法用值接收者还是指针接收者?
区别不在“能不能改字段”,而在于“要不要共享修改”和“会不会触发复制”。方法定义时写 func (s *MyStruct) Foo() 还是 func (s MyStruct) Foo(),影响调用方行为和性能。
典型问题:给结构体字段赋值后,外部变量没变;或者方法里改了字段,别的地方看不到——多半是接收者类型选错了。
- 只要方法内需要修改接收者字段,必须用指针接收者(
*MyStruct) - 结构体较大(比如含 slice、map、大数组),即使只读也建议用指针接收者,避免每次调用都复制
- 如果结构体含 mutex 等同步原语,必须用指针接收者,否则锁失效
- 同一个类型的方法集要统一:混用值/指针接收者会导致某些接口实现不完整
返回局部变量地址会怎样?
函数返回 &x(其中 x 是函数内声明的普通变量),Go 编译器通常能逃逸分析并把 x 分配到堆上,所以多数情况不会立刻崩。但这不是安全实践,逻辑一复杂就容易出错。
真正危险的是返回栈上分配的数组地址、或闭包捕获的局部变量地址——这些在函数返回后内存可能被复用,导致读到脏数据或 panic。
- 不要手动写
return &localVar,除非你明确知道逃逸分析结果且有充分理由 - 想返回新对象?用
&MyStruct{...}或new(MyStruct),语义清晰且安全 - 用
go tool compile -m看逃逸分析报告,确认变量是否真的逃逸到堆
指针不是魔法纸条,它是内存地址的直白表达。用得越直接,越要盯住生命周期和有效性。一个没检查的 nil、一次没对齐的接收者类型、一个裸奔的局部地址,都可能让程序在深夜三点安静地挂掉。


















