
Go 中声明指针变量(如 var p *string)会自动初始化为 nil,此时不能直接通过 *p = value 赋值,否则触发 panic;必须先让指针指向有效内存地址(如取已有变量地址或用 new() 分配),才能安全解引用赋值。
go 中声明指针变量(如 `var p *string`)会自动初始化为 `nil`,此时不能直接通过 `*p = value` 赋值,否则触发 panic;必须先让指针指向有效内存地址(如取已有变量地址或用 `new()` 分配),才能安全解引用赋值。
在 Go 中,指针是存储内存地址的变量,其类型决定了它能指向哪种数据。但声明 ≠ 初始化。当你写下:
var b *string
Go 会将 b 初始化为其类型的零值 —— 对所有指针类型而言,零值就是 nil。nil 指针不指向任何有效内存位置,因此对它执行解引用操作(即 *b)属于未定义行为,运行时会立即 panic:
panic: runtime error: invalid memory address or nil pointer dereference
这就是第二个代码片段失败的根本原因:
var a string = "foo" var b *string *b = "bar" // ❌ panic!b 是 nil,无法写入
✅ 正确做法是:在解引用前,确保指针已指向一块合法、可写的内存。有两大常用方式:
方式一:指向已有变量的地址(最常见)
var c string = "bar" b = &c // b 现在持有 c 的地址 *b = "world" // ✅ 合法:修改 c 的值 fmt.Println(c) // 输出 "world"
方式二:用 new() 分配新内存
b = new(string) // ✅ 分配一个 *string,返回指向新分配零值字符串的指针 *b = "bar" // ✅ 合法:该内存可写
new(T) 会分配类型 T 的零值内存,并返回 *T。等价于:
var t T return &t
⚠️ 注意事项:
- 不要混淆 new() 和 make():new() 用于任意类型,返回 *T;make() 仅用于 slice/map/channel,返回 T(非指针)。
- &c 要求 c 是可寻址的(变量、结构体字段、slice 元素等),不能对字面量或函数返回值直接取地址(如 &"hello" 非法)。
- 修改 *b 会影响其所指向的原始变量(如 c),这是 Go 中“通过指针共享状态”的基础机制。
总结:Go 的指针安全模型要求显式初始化。记住口诀:“先让指针有家,再往家里放东西” —— nil 指针没有“家”,强行写入必然崩溃。

















