Go指针是内存地址值,声明用T、取址用&x、解引用用p;需确保可寻址和非nil;传指针避免复制且可修改原值;new()零值分配,&T{}支持初始化;返回局部变量指针安全因逃逸分析;小结构体值传递更优。

Go语言指针就是变量的内存地址本身,不是值,也不是“引用”这种抽象概念——它就是一个实实在在的、可传递、可存储、可比较的地址值。
怎么声明和用对 & 与 *?
声明指针用 *T,取地址用 &x,解引用用 *p。这三个符号必须严格对应,少一个或错位置就编译失败或 panic。
-
&只能作用于「可寻址的变量」:比如name := "alice",&name合法;但&"alice"或&(1+2)直接报错 —— 字面量和临时计算结果不可取址 -
*解引用前必须确保指针非nil,否则运行时 panic:var p *int; fmt.Println(*p)会崩溃 - 结构体字段访问自动解引用:
person := &Person{Name: "Tom"}; fmt.Println(person.Name)等价于(*person).Name,不用写*
为什么函数传参要用 *T 而不是 T?
因为 Go 默认是值传递:传 T 就等于把整个值拷贝一份进函数栈;传 *T 只拷贝 8 字节(64 位系统)的地址,还能改原值。
- 改结构体字段:传
*Person才能让SetName()真正修改调用方的Person实例 - 避免大对象复制:一个含 1MB 字段的 struct,传值 ≈ 每次调用 malloc + copy;传指针几乎零开销
- 注意副作用:多个 goroutine 共享同一
*T时,字段修改不加锁会引发数据竞争
new() 和 &T{} 有什么区别?
两者都返回 *T,但语义和初始化方式不同:前者只做零值分配,后者可带字段初始化。
立即学习“go语言免费学习笔记(深入)”;
-
p := new(int)→ 分配一个int内存,值为0,返回*int -
p := &Person{Name: "Bob", Age: 25}→ 构造并初始化结构体,再取址,更常用也更直观 -
new()几乎只用于基本类型或极简场景;日常优先用&T{...},语义清晰且支持字段赋值
返回局部变量的指针安全吗?
安全。Go 编译器有逃逸分析,会自动把本该在栈上分配的变量提升到堆上,只要指针被返回,底层内存就不会被回收。
- 例如:
func NewConfig() *Config { c := Config{Port: 8080}; return &c }是完全合法且推荐的惯用法 - 不要手动模拟“栈上分配 + 返回地址”的 C 风格操作,Go 不需要也不鼓励你操心这个
- 真正要警惕的不是“能不能返回”,而是“要不要返回”:如果调用方不需要共享状态,返回值更简单、更无副作用
最容易被忽略的一点:指针不是银弹。小结构体(比如两个 int 字段)、纯计算函数、无状态转换逻辑,用值传递反而更清晰、更利于内联和逃逸优化。别为了“看起来高效”而滥用指针。










