go中指针变量的零值是nil,为类型安全的预声明标识符,非地址0x0;解引用nil指针会导致panic;需在使用前检查,如方法内加u==nil判断,或通过工厂函数确保非nil。

Go 中指针变量的零值就是 nil
声明但未初始化的指针变量,其值是 nil,和切片、map、channel、func、interface 的零值一致。这不是“空地址”或“0x0”的别名,而是 Go 语言定义的预声明标识符,类型安全且不可寻址。
常见错误现象:panic: runtime error: invalid memory address or nil pointer dereference 就是因为对 nil 指针做了解引用(比如 *p 或 p.field)。
-
var p *int→p的值是nil,p == nil为 true -
new(int)返回的是非nil指针,指向一个零值int(即0) - 函数返回指针时若未显式赋值,局部变量逃逸失败或逻辑分支遗漏,也可能返回
nil,调用方必须检查
为什么 nil 能统一表示所有指针类型的零值
Go 的 nil 不是整数 0,也不是内存地址,而是一个无类型的抽象零值——它只在编译期参与类型检查,在运行时对每个指针类型(*T)有对应底层表示(通常为全 0 位模式),但语义上不暴露细节。
这意味着:
立即学习“go语言免费学习笔记(深入)”;
-
nil不能直接转成uintptr或做算术运算;想取地址必须先确保指针已指向有效变量 - 不同类型的指针(如
*string和*int)的nil值可互相比较(都等于nil),但不能互相赋值(类型不兼容) - 接口值为
nil时,底层可能是(*T)(nil),此时if i == nil为 true;但如果接口里存了(*T)(nil),i.(*T)解包后得到的是nil指针,不是空接口
容易踩的坑:把 nil 指针当有效对象用
最典型场景是方法接收者为指针类型,但传入了 nil 实例——方法体内部若未检查就访问字段或调用其他指针方法,立刻 panic。
示例:
type User struct {
Name string
}
func (u *User) GetName() string {
return u.Name // 如果 u 是 nil,这里 panic
}
- 正确做法:在方法开头加
if u == nil { return "" }(如果语义允许) - 更稳妥的是在构造或调用侧保证非
nil,比如用工厂函数返回&User{}而非new(User)(虽然后者也不为nil,但易混淆) - JSON 反序列化到结构体指针字段时,如果源 JSON 缺失该字段,默认会设为
nil,而不是分配一个零值结构体
对比:C/C++ 的 NULL 和 Go 的 nil 不是一回事
C 的 NULL 本质是整数 0 或 ((void*)0),可以隐式转成任意指针类型;Go 的 nil 是类型化的,没有底层整数值,也不能参与运算。
-
var p *int = nil合法;var p *int = 0编译报错:cannot use 0 (untyped int) as *int value -
unsafe.Pointer(nil)合法,但unsafe.Pointer(0)不合法 - 用
reflect.ValueOf(p).IsNil()判断指针是否为nil是安全的,但注意reflect.ValueOf(&p).Elem().IsNil()才能判断p本身是否nil
真正麻烦的从来不是 nil 本身,而是忘记它可能出现在任何指针路径的任意一环——从函数返回值、结构体字段,到 map 查找结果、channel 接收值。只要涉及解引用,就得先问一句:它是不是 nil?










