笔者在一次开发过程中,发现明明函数返回了nil的error,但是收到后进行判nil是却不为空,导致认为不为空,报错甚至panic,示例代码:
type MyError struct {
// 对外的状态码
Code int
}
func (e MyError) Error() string {
return fmt.Sprint("错误码: e.Code")
}
func Product() *MyError {
return nil
}
func Check() {
var err error
err = Product()
// 这里result = true
result := err != nil
fmt.Println(result)
// 下面会空指针panic
if err != nil {
fmt.Println(err.Error())
}
}
一、nil不等于nil报错是什么原因
初看起来会让人觉得很诡异,摸不着头脑。
为什么明明返回的是 nil
,却被判定为 err ≠ nil
呢?
先了解下error,其本身是一个接口,有一个Error() 函数:
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
而对于一个变量来说,它有两个要素,一个是类型,一个是值;
对于接口变量的判断,是要同时判断类型和值均相等。
var inter interface{}
var err error
var myError *MyError
fmt.Println(inter == nil) // 输出: true
fmt.Println(err == nil) // 输出: true
fmt.Println(err == inter) // 输出: true
fmt.Println(myError == nil) // 输出: true
fmt.Println(err == myError) // 输出: false
而对于Product返回处理的err,由于product指定了返回类型,故其类型为:*error.MyError 值为:nil
fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err))
而进行err == nil 的判断时,对于nil本身,由于error类型是接口变量,而其类型不为空(为*error.MyError),所以这2个不相等。
二、nil不等于nil报错解决办法
1.不预先给值
func Check() {
// 删去这一行var err error
err := Product()
result := err != nil
fmt.Println(result)
if err != nil {
fmt.Println(err.Error())
}
}
2.类型指定为返回类型
func Check() {
var err *MyError
err = Product()
result := err != nil
fmt.Println(result)
if err != nil {
fmt.Println(err.Error())
}
}
结语
通过对上述问题的深入剖析,我们不仅解决了“nil不等于nil”的报错问题,还进一步理解了Go语言中接口变量的判断机制。这提醒我们在编程时要格外注意变量的类型和值的匹配问题,尤其是在处理接口和指针类型时。
延展阅读:
2024双11大促,如何让智能机器人客服高效生成并管理营销话术?
淘宝资损防控是什么?电商商家如何避免大促优惠叠加计算不当造成资金损失?
商家要不要报名参与京东支付双11补贴?京东支付补贴活动五大利益点有多少优惠?
咨询方案 获取更多方案详情