Go 接口与 nil:为什么「看起来是 nil」却不是
最经典的 Go 坑之一:把 nil 指针放进接口后,接口本身往往不再等于 nil。
接口值可以理解为 (动态类型, 动态值)。只有两者都「空」时,接口才等于 nil。
var p *File // p == nil
var err error = p
fmt.Println(err == nil) // false:动态类型是 *File
为何危险
函数返回 error 时,若写成 return p 而 p 是 nil 指针,调用方的 if err != nil 仍会进入错误分支。
习惯写法
- 成功路径直接
return nil,不要返回「类型化的 nil 指针」。 - 需要返回具体类型时,用命名返回值或显式分支:失败返回 err,成功返回 nil。
- 包装错误用
fmt.Errorf("...: %w", err),保持错误链可检查。
小结
判断接口是否 nil,看的是接口盒子,不是盒子里的指针。返回 error 时,宁可多写一行显式 nil。