直接回答:接口值是 (类型, 值) 的二元组,只有类型和值都为 nil 时接口才等于 nil。经典坑:函数返回 *MyError 类型,错误路径返回 nil 指针,调用方接口收到的是 (*MyError, nil)——类型非 nil,所以 err != nil 为真,后续调用方法可能 panic。这就是" typed nil "问题,被官方 FAQ 单列。

展开解析:规避纪律:返回接口类型的函数,无错误时直接返回 nil 字面量,绝不要返回一个可能为 nil 的具体类型变量。例如不要写 var e *MyError; if bad { e = ... }; return e,而要 if bad { return &MyError{...} }; return nil。检测 typed nil 只能反射(reflect.ValueOf(v).IsNil())或约定接口方法行为,业务代码不该走到这步。相关细节:nil 接口调用方法直接 panic;interface{} 与 nil 比较是类型感知比较,两个不同类型非 nil 值也不相等。这个设计的理由是一致性:接口持有的是"类型加值",nil 指针依然是合法值(方法接收者可以是 nil 指针并正常处理),语言不替你猜意图。

追问方向:为什么接收者为 nil 指针的方法可以正常执行?json.Unmarshal 到接口时类型是什么?如何用 reflect 安全检测 typed nil?

(约 420 字)