结论

interface 本质上也是一种类型,所以在判断它是否为 nil 时,

如果是其它类型转成的 interface,其实中间已经包含了结构体信息,所以这时它已经不是 nil 了

背景

此文是由一个 bug 引发的思考,代码如下

业务代码

代码经过精简,请暂时忽略注释的的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type myError struct {}

func (myError)Error() string {
	return "my error"
}

//func f2() error {
func f2() *myError {
	return nil
}

func f1() error {
	return f2()
	//e:= f2()
	//if e == nil {
	// return nil
	//}
	//return e
}

func main() {
	err := f1()
	if err != nil {
		fmt.Println("not nil")
	}else {
		fmt.Println("nil")
	}
}

可以先浏览下代码,猜下 err 是不是 nil


以上的代码最终输出是not nil

起初结果让我摸不着头脑。

理一下思路,main 函数中的 err 其实是一个 叫 error 的 interface,

f2 函数返回了一个空指针 *myError(结构体实现了 error 接口)

这两个类型一个为 interface 一个为 myError,这里发生了一次隐式类型转换

main 函数第2行本质上是判断 err 是否与 interface 的 nil 值相等

解决方案

如上注释内容

  1. f2 的声明就返回 error 的 nil 值(推荐方法)

  2. f1 中再判断一次,返回 error 的 nil 值


这篇文章对 interface 有详细的论述

Golang interface