Go中指针变量默认初始化为nil,需用&取地址或new()分配内存才能安全使用;禁止对字面量取地址;解引用nil指针会panic。

怎么声明并初始化一个指针变量
Go 中不能直接声明未初始化的指针变量为 nil 以外的值,所有指针变量默认初始值都是 nil。要让它指向有效内存,必须用取地址符 & 显式获取某个变量的地址,或者用 new() 分配零值内存。
-
var p *int→p是*int类型,值为nil,此时解引用会 panic -
var x int = 42; p := &x→ 安全:p指向栈上变量x -
p := new(int)→ 返回指向新分配的零值int的指针(等价于new(int) == &zero_int)
为什么不能对字面量直接取地址
Go 禁止对临时值(如字面量、函数返回值)取地址,因为它们没有确定的内存生命周期。比如 &42 或 &(x + y) 都会编译报错:cannot take the address of ...。
- 错误写法:
p := &42→ 编译失败 - 正确写法:先赋给变量再取址 ——
val := 42; p := &val - 或用
new()替代:p := new(int); *p = 42
new() 和 & 变量的区别在哪
两者都返回指针,但语义和内存位置不同:&x 指向已有变量(可能在栈或逃逸到堆),new(T) 总是在堆上分配零值 T 并返回其地址。
func example() {
// &x:x 可能被优化到栈上(除非逃逸)
x := 100
p1 := &x
// new(int):明确在堆分配,返回 *int 指向零值(即 0)
p2 := new(int) // 等价于:p2 := &int(0)
fmt.Println(*p1, *p2) // 输出:100 0
}
-
new(T)只能创建零值,无法指定初始内容 - 若需非零初始值,必须先
new(T)再赋值,或用&T{...}复合字面量(适用于结构体等) - 对基本类型(如
int、string),&T{v}不合法,只能用变量 +&或new()+ 赋值
常见 panic 场景:解引用 nil 指针
这是 Go 中最典型的指针错误。只要对值为 nil 的指针执行 *p 操作,运行时就 panic:invalid memory address or nil pointer dereference。
立即学习“go语言免费学习笔记(深入)”;
- 典型误用:
var p *string; fmt.Println(*p)→ 直接 panic - 安全习惯:使用前检查是否为
nil,尤其在函数参数或结构体字段中接收指针时 - 结构体中嵌入指针字段(如
type User struct { Name *string }),JSON 反序列化后该字段可能为nil,直接*u.Name很危险
指针本身不复杂,难的是判断“它到底有没有被正确定向”——尤其是跨函数传递、从 JSON/DB 加载、或用 new() 后忘记赋值时,容易漏掉这层检查。










