go自定义的错误返回nil != nil 的问题
func returnsError() error {
	var p *MyError = nil
	if bad() {
		p = ErrBad
	}
	return p // Will always return a non-nil error.
}

上面返回的  p  永远不会与 nil 相等。

这是为什么呢,因为 error 是一个 interface,从类型比较可以知道,interface 之间比较需要保证两者的 TypeValue 两两相等:

  • 语言内的  nil  可以理解为一个 TypeValue 均为空的 interface
  • 代码里面返回的 p 虽然 Value 为空,但是 Type 是 *MyError

所以 p!=nil 。

正确的代码应该是这样的:

func returnsError() error {
	if bad() {
		return ErrBad
	}
	return nil
}

这个问题不仅仅是抛出错误的时候会出现,任何返回 interface 的场景都需要注意。

Go 类型可比较与可排序约定

TypeComparableOrderedDescription
Boolean
Integer
Float
Complex分别比较实数和虚数,同时相等则两个复数相等。 如果需要比较大小,需要开发者分别比较实数和虚数。
String基于字节逐个比较。
Pointer如果两个指针指向同一个对象或者都为 nil,则两者相等。
Channel类似 Pointer,两个 Channel 变量只有都为 nil,或者指向同一个 Channel 的时候才相等。
Interface两个 interface 的 Type 和 Value 值同时相等时,两者才相等。
Struct⚠️仅当 Struct 内所有成员都是 Comparable,这个 Struct 才是 Comparable 的。 如果两个 struct 类型相同,且所有非空成员变量都相等,则两者相等。
Array⚠️仅当成员为 Comparable,Array 才是 Comparable 的。 如果两个 Array 中的每一个元素一一相等时,则两个 Array 相等。
Map
Slice
Func

参考 : 深入理解 Go Comparable Type Go FAQ