Go 接口与 nil:为什么「看起来是 nil」却不是

最经典的 Go 坑之一:把 nil 指针放进接口后,接口本身往往不再等于 nil。

接口值可以理解为 (动态类型, 动态值)。只有两者都「空」时,接口才等于 nil

var p *File // p == nil
var err error = p
fmt.Println(err == nil) // false:动态类型是 *File

为何危险

函数返回 error 时,若写成 return pp 是 nil 指针,调用方的 if err != nil 仍会进入错误分支。

习惯写法

  • 成功路径直接 return nil,不要返回「类型化的 nil 指针」。
  • 需要返回具体类型时,用命名返回值或显式分支:失败返回 err,成功返回 nil。
  • 包装错误用 fmt.Errorf("...: %w", err),保持错误链可检查。

小结

判断接口是否 nil,看的是接口盒子,不是盒子里的指针。返回 error 时,宁可多写一行显式 nil