Go 的接口值是 (类型, 值) 的二元组。只有类型和值都为 nil 时,接口才等于 nil。把一个 nil 指针赋给接口,类型字段非 nil,接口判空就失败——这是 Go 面试和线上事故中的经典陷阱。

func getErr() error {
    var e *MyError // nil 指针
    return e       // 返回时包装成 (type=*MyError, value=nil)
}
err := getErr()
fmt.Println(err == nil) // false!

解析:调用方看到 err != nil 以为出错去处理,实际 *MyError 是 nil,调用其方法可能 panic(除非方法做了 nil receiver 保护)。规范做法:函数内部应显式 return nil,返回接口零值,而不是返回类型化的 nil 指针。

避免方式:

  • 返回 error 或接口的函数,无错误时直接 return nil;
  • 必须判断底层时可用 reflect.ValueOf(v).IsNil(),但要先确认 Kind 是指针类;
  • 评审时警惕'先声明具体类型变量再作为接口返回'的写法。

追问方向:eface 与 iface 的结构差异、nil receiver 方法为何有时安全、接口动态分派。