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 之间比较需要保证两者的 Type 和 Value 两两相等:
- 语言内的
nil可以理解为一个Type和Value均为空的interface - 代码里面返回的
p虽然Value为空,但是Type是*MyError
所以 p!=nil 。
正确的代码应该是这样的:
func returnsError() error {
if bad() {
return ErrBad
}
return nil
}这个问题不仅仅是抛出错误的时候会出现,任何返回 interface 的场景都需要注意。
Go 类型可比较与可排序约定
| Type | Comparable | Ordered | Description |
|---|---|---|---|
| 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 | ❌ | ❌ |