
Go 中声明指针变量(如 var p *string)会自动初始化为 nil,此时不能直接解引用赋值(如 *p = "x"),否则触发 panic;必须先让指针指向一个有效的内存地址(如取已有变量地址或用 new() 分配)。
go 中指针的首次赋值:理解 nil 指针与有效内存地址的区别
在 Go 中,指针变量的声明与使用需严格区分「声明」和「初始化」两个阶段。声明指针(如 var b *string)时,若未显式初始化,其值自动为 nil —— 这是所有指针类型的零值。nil 表示该指针当前不指向任何有效内存地址,因此*对 nil 指针进行解引用(即 `b = ...`)会导致运行时 panic**:
panic: runtime error: invalid memory address or nil pointer dereference
这正是第二个代码片段失败的根本原因:
var b *string *b = "bar" // ❌ panic!b 是 nil,无法写入
而第一个示例能正常运行,是因为它通过 b = &c 显式将 b 初始化为变量 c 的地址,使 b 指向一块合法、可写的内存空间:
var c string = "bar" b = &c // ✅ b 现在指向 c 的内存地址 *b = "world" // ✅ 安全:修改 c 的值 fmt.Println(c) // 输出 "world"
正确初始化指针的两种常用方式
-
指向已有变量(最常见)
var s string = "hello" p := &s // p 指向 s *p = "world" // s 变为 "world"
-
动态分配新内存(使用 new 或 &struct{})
p := new(string) // 分配一个 *string,初始值为 ""(string 零值) *p = "hello" // ✅ 安全赋值
或更现代的写法(推荐):
p := &string{"hello"} // 直接创建并取地址
关键注意事项
- ✅ &variable 总是安全的(只要 variable 是可寻址的,如局部变量、结构体字段等);
- ❌ 对 nil 指针解引用(读或写)均会 panic;
- ⚠️ 切片、map、channel 等引用类型也遵循类似规则:声明后为 nil,需 make 或字面量初始化才能使用;
- ? 可用 p == nil 显式检查指针是否有效,避免意外 panic。
总之,Go 的指针设计强调显式性与安全性:你必须明确告诉编译器“这个指针要指向哪里”,才能安全地操作其所指内存。这不是限制,而是防止悬空指针和未定义行为的关键保障。











