【发布时间】:2018-04-11 07:11:10
【问题描述】:
我已经实现了一个自定义错误类型,并且在 nil 值方面确实出现了奇怪的行为。当我将自定义错误作为标准错误接口传递时,即使自定义错误返回为 nil,它也永远不会被识别为 nil。
看看这个小测试程序:
package main
import (
"fmt"
"strconv"
)
type CustomError struct {
Code int
}
func (e *CustomError) Error() string {
return strconv.Itoa(e.Code)
}
func FailCustom(dofail bool) *CustomError {
if dofail {
return &CustomError{Code: 42}
} else {
return nil
}
}
func WrapFailCustom(dofail bool) error {
return FailCustom(dofail)
}
func main() {
err := WrapFailCustom(false)
if err == nil {
fmt.Println("err is nil")
} else {
fmt.Println("err is not nil")
}
}
在操场上也一样:https://play.golang.org/p/7bqeDw5B5fU
这确实会输出“err is not nil”。
我本来希望 *CustomError 类型的 nil 值隐式转换为 error 类型的 nil 值。谁能向我解释一下,为什么不是这种情况以及如何正确传播自定义错误类型的 nil 值?
编辑: 正如 Iain Duncan 所指出的,可以在 here 找到对此的解释
为了进一步探讨这个问题,让我们考虑对 WrapFailCustom 进行以下修改:
func WrapFailCustom(dofail bool) error {
err := FailCustom(dofail)
if err == nil {
return nil
} else {
return err
}
}
这实际上返回“err is nil”:https://play.golang.org/p/mEKJFyk5zqf
依赖这个作为解决方案我确实感觉很糟糕,因为在使用会吐出我的自定义错误的函数时很容易忘记它。有没有更好的方法来制作自定义错误来防止这种“歧义”的发生?一直使用基本错误类型的明显解决方案,对于消耗像 WrapFailCustom 这样的函数的代码来说似乎真的很不方便,所以我想避免这种情况......
【问题讨论】:
-
有一个非常好的 gopher con 讨论了不同类型的 nil,包括接口指针 nil 与接口 nil 不同的常见错误。 youtu.be/ynoY2xz-F8s
标签: pointers go error-handling interface null