
Go 中声明指针变量(如 var p *string)会自动初始化为 nil,此时不能直接解引用赋值(如 *p = "x"),否则触发 panic;必须先让指针指向有效内存地址(如取已有变量地址或用 new() 分配)。
go 中声明指针变量(如 `var p *string`)会自动初始化为 `nil`,此时不能直接解引用赋值(如 `*p = "x"`),否则触发 panic;必须先让指针指向有效内存地址(如取已有变量地址或用 `new()` 分配)。
在 Go 中,指针变量的生命周期始于其零值 —— nil。这意味着当你写下:
var b *string
编译器会为 b 分配一个指针类型的存储空间,并将其初始化为 nil(即“不指向任何地址”)。此时 b 是合法的、安全的变量,但它尚未关联任何可写入的内存位置。若立即执行:
*b = "bar" // ❌ panic: invalid memory address or nil pointer dereference
程序将在运行时崩溃,因为 Go 无法向“空地址”写入数据。
✅ 正确的首次赋值方式
要使指针可解引用并赋值,必须先让它指向一块有效的、可寻址的内存。常见方式有两种:
1. 指向已存在的变量(最常用)
var c string = "bar" b := &c // b 现在指向变量 c 的内存地址 *b = "world" // ✅ 合法:修改 c 的值 fmt.Println(c) // 输出 "world"
2. 使用 new() 动态分配内存
b := new(string) // 分配一个 *string,内部指向新分配的零值 string(即 "") *b = "hello" // ✅ 合法:修改该匿名 string 的值 fmt.Println(*b) // 输出 "hello"
? 注意:new(T) 返回 *T,并自动将所分配的 T 初始化为其零值(如 string → "", int → 0)。
⚠️ 关键区别:声明 vs. 解引用赋值
- b = &c 是给指针变量 b 赋值一个地址(安全操作);
- *b = "x" 是给 b 所指向的内存位置赋值(前提是 b != nil)。
错误示例的本质问题在于跳过了地址初始化步骤:
var b *string // b == nil *b = "bar" // 尝试向 nil 地址写入 → panic
而正确示例显式建立了有效指向关系:
var c string = "bar" b := &c // b now points to c's memory *b = "world" // modifies c via b → safe & expected
? 验证与调试建议
可通过打印指针值确认是否为 nil:
fmt.Printf("b = %p\n", b) // nil 指针输出 <nil>也可使用 if b == nil 显式检查,避免意外解引用。
✅ 总结
- 所有 Go 指针变量默认初始化为 nil;
- nil 指针可安全读取(如 fmt.Println(b)),但不可解引用写入;
- 首次使用前,务必通过 &existingVar 或 new(T) 初始化指针;
- 这一机制是 Go 内存安全设计的重要体现——强制开发者明确内存归属,杜绝悬空指针和未定义行为。

















