Go 语言里一个经典的「天才设计」(其实很多人觉得是坑)——接口的 nil 与具体类型的 nil 不一样。
详细解释:
type MyError struct {
msg string
}
func (e *MyError) Error() string { return e.msg }
func getError() error {
var err *MyError = nil // 这里 err 是一个「类型为 *MyError、值为 nil」的指针
return err // 返回给 error 接口
}
func main() {
e := getError()
fmt.Println(e == nil) // 输出 false
}
为什么不是 true?
error是一个接口类型(interface)。- 接口在底层其实是两个部分:类型信息 + 数据。
- 当你把
var err *MyError = nil返回给error接口时,Go 会把: - 类型信息 设为
*MyError - 数据 设为
nil - 所以接口
e的实际状态是:有类型,但数据为空,因此e == nil判断为false。
var e error = nil 这种直接给接口赋 nil)时,e == nil 才会是 true。正确写法(推荐)
func getError() error {
return nil // 直接返回 nil,接口就是彻底的 nil
}
// 或者如果你真的想返回自定义错误:
func getError() error {
if someCondition {
return &MyError{msg: "出错了"}
}
return nil // 明确返回接口 nil
}
这个设计在 Go 里极其常见(尤其是 error 处理),几乎所有 Go 程序员都被坑过一次 😂
总结:**返回 *T 类型的 nil 给接口 ≠ 接口是 nil**,这就是 Go 的「天才之处」。