指针变量直接用 == nil 判断最安全,因所有指针类型零值即 nil;结构体字段是指针时须单独判空;err == nil 是唯一合法错误判空方式;接口变量为 nil 需动态类型和值均为空。

指针变量直接用 == nil 判断最安全
Go 中所有指针类型(*int、*string、*MyStruct 等)的零值就是 nil,声明后未赋值即为 nil,可直接比较:if p == nil。这不仅是语法允许的,更是 Go 的语言契约——无需额外函数或反射。
常见错误是把非指针类型误当指针来判空,比如对 string、int、struct 写 == nil,编译直接报错。记住:只有指针、切片、map、chan、func、interface 这六类能和 nil 比较;其中只有指针才是“真正的指针”。
典型防护写法:
if p != nil {
fmt.Println(*p)
}
结构体字段是指针时必须单独判空
结构体本身是值类型,永远不为 nil,哪怕所有字段都是指针:type User struct{ Name *string },u := User{} 后,u == nil 会编译失败。
立即学习“go语言免费学习笔记(深入)”;
真正要检查的是字段本身是否为空:
-
if u.Name != nil→ 安全解引用*u.Name -
if u.Profile != nil && u.Profile.ID > 0→ 避免panic: invalid memory address - 函数参数接收
*User时,开头就该if u == nil { return errors.New("user required") }
别指望结构体整体“空”了字段就自动空——每个指针字段都得自己管。
err == nil 是唯一合法的错误判空方式
Go 的 error 是接口类型,但它的判空逻辑被语言契约严格约束:成功返回 nil,失败返回非 nil 的 error 值。所以只有一种写法正确:if err == nil。
其他写法全是陷阱:
-
errors.Is(err, nil)→ 编译报错,errors.Is不接受nil -
var i interface{} = err; if i == nil→ 即使err是nil,只要它曾是具体类型(如*os.PathError),i就不等于nil -
err != nil && err.Error() != ""→ 某些自定义error的Error()方法可能 panic,还没打印就崩了
判空必须在任何使用 err 之前完成,且只用一次 ==。
别混淆 interface{} 为 nil 和它装的指针为 nil
接口变量是否为 nil,取决于它的动态类型和动态值是否都为空。这是最容易翻车的地方。
例如:
-
var w io.Writer = nil→w == nil为 true -
var buf *bytes.Buffer; var w io.Writer = buf→w == nil为 false,即使buf本身是nil(因为类型已确定为*bytes.Buffer)
想检查底层指针是否为空,必须先类型断言:
if b, ok := w.(*bytes.Buffer); ok && b == nil {
// 底层指针确实为空
}
传参时避免把裸指针塞进 interface{},否则调用方无法靠 == nil 可靠判断——语义已经丢失了。


















